c - fork 进程,信号量,为什么这个输出?

标签 c linux fork ipc semaphore

我有一个类型为 char 的数组 boxIn[],其中包含 R R G B G B O Y O O P R 个字符。 boxIn[] 在共享内存中。共享内存 p 中还有一个 char*,其值为 boxIn[ 中的 char 之一] 数组。

程序中定义了两个信号量如下:

/* initialize semaphores */
if((sem_init(&sem, pshared, value)) == 1){      /* only 2(value) processes at the same time */
    perror("Error initializing synch semaphore\n");
    exit(1);
}
if((sem_init(&mutex, pshared, 1)) == 1){        /* only 1 processes at the same time */
    perror("Error initializing synch semaphore\n");
    exit(1);
}

我从 for 循环中 fork child :

/* fork child processes */
for(i=0; i<n ; i++){
    pid = fork();
    if(pid < 0){    /* check for error  */
        printf("Fork error.\n");
    }
    else if(pid == 0) break;    /* child processes */

}

然后我让 children 做一些处理。目前,我正在努力逐步实现我的目标。因此,我只更改了一次 *p 的值。

/******************************************************/
/******************   PARENT PROCESS   ****************/
/******************************************************/
if(pid != 0){
    while(wait()>0);
}

/******************************************************/
/******************   CHILD PROCESS   *****************/
/******************************************************/
else{
    while(*p != boxIn[i]); /* wait until it's my turn */
    sem_wait(&sem);
    printf("%c boxes are being painted.\n",boxIn[i]);
    printf("Done painting.\n");
    sleep(1);
    sem_wait(&mutex);
    if(*p=='R') *p='G';
    sem_post(&mutex);
    sem_post(&sem);
    exit(1);
}

但是我确实得到了意外的输出:

我期望的是:

R boxes are being painted.
R boxes are being painted.
Done.
Done.
R boxes are being painted.
Done.
G boxes are being painted.
G boxes are being painted.
Done.
Done.

我得到的结果如下:

R boxes are being painted.
Done painting.
R boxes are being painted.
Done painting.
R boxes are being painted.
Done painting.
G boxes are being painted.
Done painting.
G boxes are being painted.
Done painting.
varaquilex@computer ~/Dropbox/Courses/BLG312E - Computer Operating Systems/hw3 $ G boxes are being painted.
Done painting.
G boxes are being painted.
Done painting.
G boxes are being painted.
Done painting.
G boxes are being painted.
Done painting.
G boxes are being painted.
G boxes are being painted.
Done painting.
Done painting.
G boxes are being painted.
Done painting.
G boxes are being painted.
Done painting.
P boxes are being painted.
Done painting.
P boxes are being painted.
Done painting.
P boxes are being painted.
Done painting.
P boxes are being painted.
Done painting.
P boxes are being painted.
Done painting.
^C

问题是:即使 boxIn[] 中只有 2 个 G 框,为什么我绘制了 2 个以上的 G 框数组,更重要的是,如何我什至绘制了 P 框,更不用说数组中只有一个 P 框了,我得到许多 P 框画?

注意:我试了很久。更不用说我在这之前用 shift+C 停止了很多程序。我重新启动了终端并得到了这个输出。更有趣的一点是,我尝试打印 i 的值以及正在绘制的框,但我看到输出混淆了!我的意思是,即使 printf()printf("%c boxes(%d) are being painted",boxIn[i],i);。这很尴尬,我重新启动了操作系统并从同一个程序中得到了不同的输出。有人可以向我解释为什么会发生这种情况以及如何防止这种情况再次发生吗?

最佳答案

为了使用进程共享信号量,它们必须在共享内存中。你的不是。所以在 fork 之后,每个进程都有自己的信号量副本。分配共享内存最简单的方法是:

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

然而,尽管匿名映射几乎普遍可用,但 POSIX 中并未指定匿名映射,因此,正式地,“不可移植”。另一种可移植的方法是创建一个临时文件或 POSIX 共享内存对象。

或者(这里是推荐方式),使用sem_open代替sem_init

关于c - fork 进程,信号量,为什么这个输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16387348/

相关文章:

perl - 当 parent 被杀时杀死 child

linux - 为什么我必须为子进程设置 `wait()`?

c - 我应该添加哪个库来解决 fcntl64、stat64 等问题?

c - WIndows系统编程使用标准C库

c++ - 在 linux 上的 c++/Qt 中触发并忘记线程的最简单方法是什么?

c++ - 跟踪进程和所有 fork 进程的系统调用

operating-system - 父进程在写时复制期间会失去写能力吗?

c - sscanf 目标地址溢出

C - 多个左值错误

linux - 发出 'stop' 命令后 Tomcat 启动