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

问题描述

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

#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

我们将不胜感激。

解决方法

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

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返回的是创建的信号量的地址。但是,您正在取消引用该地址,并将内容的副本放入您的可变内容中。这意味着实际上不是您创建的信号量,而仅仅是保存状态信息的结构的副本。结果是与代码中的事物进行交互实际上并没有与您的意图进行交互。 (实际上,如果您检查sem_wait()和sem_getvalue()的返回值,可能会得到一些不正确的提示。)

如果您改为将东西作为信号灯的指针并与其进行交互,则会得到以下输出:

done
processOneThing: 0

这是您想看到的。您可以在此处尝试更正的代码:

Runnable corrected code