如何检查c中信号量的状态?

Posted

技术标签:

【中文标题】如何检查c中信号量的状态?【英文标题】:How can I check the state of a semaphore in c? 【发布时间】:2012-07-19 11:16:17 【问题描述】:

我有一个全局静态变量,它是一个信号量,因为我正在编写一个库而不是一个程序。

在使用该库的main() 程序中,有fork() 的调用,以及基于共享内存的对管道的读取和写入。

例如,这是使用我的库的main()

#include <stdio.h>
#include <stdlib.h>
#include "my_pipe_shared_memory_based.h"
int main()


    int spd, pid, rb;
    char buff[4096];
    my_new_init();

    if (my_new_fifo("tmp_shm_pipe",0666) < 0)
    
        perror("my_new_fifo");
        exit(1);
    

    if (fork()) 
    
        spd = my_new_open("tmp_shm_pipe", O_RDONLY, 0600);
        if (spd < 0)
        
            perror("PARENT: my_new_open");
            exit(1);
        
        rb = my_new_read(spd, buff, sizeof(buff));
        if (rb > 0)
            write(1, buff, rb);
    

    else
    
        spd = my_new_open("tmp_shm_pipe", O_WRONLY, 0600);
        if (spd < 0)
        
            perror("SON: my_new_open");
            exit(1);
        
        my_new_write(spd, "hello world!\n", sizeof("hello world!\n"));
    

    my_new_close(spd);
    my_new_un_link("tmp_shm_pipe");
    my_new_finish();

    return 0;

现在,我想在每次进程在方法中读取和/或写入之前使用信号量:

    my_new_write()

    my_new_read()

现在,问题是,我怎样才能在上面请求的方法中每次检查信号量的状态(例如my_new_write&my_new_read),所以我可以让进程做他的事情,或者阻止它,如果另一个进程当前正在读/写?

谢谢

【问题讨论】:

您的信号量“mySemaphore”在不同进程中不可见。看我的回答。 您也可以简单地尝试在 sem_open 调用中将“S_IRUSR | S_IWUSR”替换为“S_IRWXO”。它应该可以工作,虽然我不确定:) @JoãoFernandes:试过了,但输出仍然只是:Output: 而不是 :Output:hello world!。也许还有其他想法?谢谢 您是否验证过您的信号量正在正确初始化,并且--once--,而不是每个进程一次?您的每个信号量操作的返回码是什么? @SanJacinto:是的,我加倍检查了。它从零 (0) 开始,到 1,然后回到零。从不大于 1 或小于 0。 【参考方案1】:

这里的关键是您必须确保确保互斥的信号量对两个进程都是可见的。为此,您需要分配共享内存并在分叉之前初始化信号量。例如,对于这个任务,您可以使用 mmap。示例(没有任何错误检查):

sem_t *sem = mmap(NULL, sizeof(sem_t),
                  PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0);

之后,使用 sem_init 初始化信号量并确保第二个参数 pshared 不为零。手册说:

如果 pshared 不为零,则信号量在进程之间共享,并且应该位于共享内存区域中(请参阅 shm_open(3)、mmap(2) 和 shmget(2))。 (由于 fork(2) 创建的子进程继承了其父进程的内存映射,它也可以访问信号量。)任何可以访问共享内存区域的进程都可以使用 sem_post(3)、sem_wait(3) 等对信号量进行操作.

最后fork进程,正常使用sem_wait和sem_post。

编辑:

真的,尝试替换这个:

mySemaphore = sem_open("mySemaphore", O_CREAT, S_IRUSR | S_IWUSR);

有了这个:

mySemaphore = mmap(NULL, sizeof(sem_t),
                   PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0);
sem_init(mySemaphore, 1, 1);

在 my_new_open 函数中

【讨论】:

您似乎正确地创建了共享内存区域,但绝对不是信号量。 那行sem_init(mySemaphore, 1, 1); 导致死锁,程序没有停止运行。奇怪..我什至无法调试代码,因为我在 main() 中是 forking。我检查了sem_initman 和最后一个1(最右边的操作数)应该确实是1 表示互斥,但仍然处于僵局。 @ron,仔细查看您的代码,您似乎还有其他问题。例如,读取似乎是非阻塞的,这可能是问题的根源,因为您可能希望等到管道中有可用数据。【参考方案2】:

sem_trywait() 和 sem_wait() 不是您要找的东西吗?用信号量句柄调用它们,你就会知道它们的状态。

http://pubs.opengroup.org/onlinepubs/7908799/xsh/sem_trywait.html

不确定信号量,但带有互斥锁的 pthread_cond_timedwait() 还可以让您检查同步状态而不会阻塞线程(或给出超时)。

【讨论】:

Victor,我已经尝试过了(我的意思是线程)。现在我尝试使用 sem_waitsem_post 但代码仍然不同步。有什么想法吗?我应该发布代码吗?谢谢 肯定的,把读/写函数贴出来,我们看看。 完成了,我发布了 3 个方法:openreadwrite。谢谢。

以上是关于如何检查c中信号量的状态?的主要内容,如果未能解决你的问题,请参考以下文章

Linux 上的 Ctrl+C 等终止信号或中断

如何使用 Matlab 检查视频中的音频信号

如何发送 XInput 按钮?

如何在任意逻辑状态图之间发送信号?

C++中的多线程,只检查信号量是不是被锁定

C++0x 没有信号量?如何同步线程?