1

I have an array boxIn[] of type char that contains R R G B G B O Y O O P R characters. boxIn[] is in shared memory. There is also a char* in shared memory, p, that has a value of one of the chars in the boxIn[] array.

There are two semaphores defined in the program as follows:

/* 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);
}

I fork the children from a for loop:

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

}

Then I let the children do some processing. At the moment I'm trying to get to my goal step by step. Therefore I change *p's value only once.

/******************************************************/
/******************   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);
}

However I do get an unexpected output:

What I expect is:

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.

And what I get is as follows:

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

Question is: why do I get more than 2 G boxes painted even though there are only 2 G boxes in the boxIn[] array, and more importantly how do I even get P boxes painted, not to mention there is only one P box in the array and I get many P boxes painted?

Note: I have been trying for a long time. Not to mention that I used shift+C to stop many programs before this one. I restarted terminal and got this output. More interesting point is, I tried to print the value of i along with the box being painted and i saw that the output was mixed up! I mean, there were some rows that show G boxes(3) are being painted and some others were G boxes are being painted even though the printf() was printf("%c boxes(%d) are being painted",boxIn[i],i);. This is awkward, I restarted the operating system and got a different output from the same program. Can someone explain me why this occurs and how can I prevent this from occurring once again?

4

1 回答 1

2

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

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

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

或者(这是推荐的方式),使用sem_open而不是sem_init.

于 2013-05-05T20:41:14.060 回答