奇怪的 POSIX 信号量行为(卡在 Linux 上的 sem_wait 上)

Posted

技术标签:

【中文标题】奇怪的 POSIX 信号量行为(卡在 Linux 上的 sem_wait 上)【英文标题】:Strange POSIX semaphore behavior (stuck on sem_wait on Linux) 【发布时间】:2019-10-11 22:58:35 【问题描述】:

我正在尝试解决一个涉及 POSIX 信号量的学校问题。我遇到了一个问题,我已将其范围缩小到此简化代码:

sem_t sem;

void parent() 
    printf("waiting...\n");
    sem_wait(&sem);
    printf("done!\n");


void child() 
    sem_post(&sem);
    printf("go!\n");
    exit(0);


int main() 
    sem_init(&sem, 1, 0);

    if(!fork())
        child();

    parent();

    sem_destroy(&sem);

    exit(0);

在 Linux 中编译(使用gcc -Wall -pthread sems.c -o sems)并运行此程序时,我得到以下输出(程序未完成执行):

waiting... 
go!

因为我在子进程中调用sem_post(&sem),所以我希望父进程越过sem_wait(&sem),输出为:

waiting...
go!
done!

更奇怪的是,出于好奇,我尝试使用 CLion(Cygwin 编译器)在 Windows 上对其进行测试,并且程序按预期运行。我在这里错过了什么?

【问题讨论】:

【参考方案1】:

来自man page of sem_init()

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

您的sem 变量未在共享内存中分配;因此,尽管pshared 参数不为零,但它不能在进程之间共享。每个进程都有自己独特的信号量实例。

【讨论】:

@cabralpinto Cygwin 做了各种奇怪的事情来尝试解决 Windows 缺乏与 fork() 等等效项的问题。毫不奇怪,它的行为与真正的 Linux 或 Unix 环境不同。 在这种情况下,posix semaphore api 看起来像是在原生 Win32 信号量之上的一个薄包装器,它在某些事情上有微妙的不同语义。

以上是关于奇怪的 POSIX 信号量行为(卡在 Linux 上的 sem_wait 上)的主要内容,如果未能解决你的问题,请参考以下文章

linux c编程:Posix信号量

linux进程间通信之Posix 信号量用法详解代码举例

Linux 信号量之Posix基于内存的信号量

linux:线程 POSIX信号量&&线程池

在 Linux 内核命名空间之间使用 POSIX 信号量

Linux系统编程POSIX有名信号量