子进程中的命名信号量让我感到困惑

Named Semaphores in child processes confusing me

我有这个非常简单的程序来测试命名信号量:

#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <sys/shm.h>
#include <fcntl.h>

sem_t thing;

void processOne() {
    sleep(1);
    int l;
    sem_getvalue(&thing, &l);
    printf("processOneThing: %d\n", l);
}

void processTwo(){
    sem_wait(&thing);
    printf("done");
}

int main(int argc, char **argv) {
    int pidOne, pidTwo;
    thing = *sem_open("/testest", O_CREAT|O_EXCL,0777,1);
    pidTwo=fork();
    if(pidTwo==0){
        processTwo();
    }
    else{
        pidOne=fork()
        if(pidOne==0){
            processOne();
        }
        else{
        }
        wait(&pidTwo);
        wait(&pidOne);
    }
    sem_unlink("/testest");
    sem_close(&thing);
}

输出为:

doneprocessOneThing: 1

这意味着第二个进程递减了信号量,但是它在第一个子进程中的值仍然是 1...

我不知道我做错了什么,我查看了命名信号量文档,但找不到太多可以帮助我解决这个问题的信息。

我正在编译使用:

gcc test.c -pthread

我们将不胜感激。

首先,代码缺少;在此行的末尾:

else{
pidOne=fork()    <------ here
if(pidOne==0){
processOne();
}

它无法为 wait() 原型#include。但是纠正这些问题我得到了和你一样的输出。那么发生了什么?问题在于您如何创建信号量:

sem_t thing;
... 
thing = *sem_open("/testest", O_CREAT|O_EXCL,0777,1);

来自sem_open的return是创建的信号量的地址。但是您正在取消对该地址的引用并将内容的副本放入您的变量中。这意味着 thing 实际上不是您创建的信号量,而只是保存状态信息的结构的副本。结果是与代码中的事物交互实际上并不是与您想要的交互。 (事实上​​ ,如果您检查 sem_wait() 和 sem_getvalue() 上的 return 值,您可能会得到一些不正确的指示。)

如果您将 thing 设为指向信号量的指针并与之交互,您将得到以下输出:

done
processOneThing: 0

这是我认为你期望看到的。您可以在此处尝试更正后的代码:

Runnable corrected code