分叉进程,信号量,为什么这个输出?

时间:2013-05-05 17:52:53

标签: c linux fork ipc semaphore

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

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

/* 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 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 */

}

然后我让孩子们做一些处理。目前我正在努力逐步实现目标。因此,我只更改*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

问题是:为什么即使G数组中只有2个G框,我也会获得超过2个boxIn[]框,更重要的是如何我甚至画了P个框,更不用说数组中只有一个P框了,我画了很多P个框?

注意:我已经尝试了很长时间。更不用说我使用shift + C在此之前停止了许多程序。我重新启动终端并获得此输出。更有意思的是,我试图打印i的值以及正在绘制的框,我看到输出混合了!我的意思是,即使G boxes(3) are being paintedG boxes are being painted,也有一些行显示printf()而其他一些行printf("%c boxes(%d) are being painted",boxIn[i],i);。这很尴尬,我重新启动了操作系统并从同一程序获得了不同的输出。有人可以解释为什么会发生这种情况,我该如何防止这种情况再次发生?

1 个答案:

答案 0 :(得分:2)

为了使用进程共享信号量,它们必须位于共享内存中。你的不是。所以在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