#include <semaphore.h>
int main(void)
{
int pfds[2];
char buff[20];
sem_t sem;
sem_init(&sem, 1, 1);
pipe(pfds);
if (!fork()) {
printf("Child: Waiting to acquire semaphore\n");
sem_wait(&sem);
printf("child acquires lock\n");
sleep(5);
write(pfds[1], "Hello", 6); /* make stdout same as pfds[1] */
close(pfds[0]); /* we don't need this */
printf("child releases lock\n");
sem_post(&sem);
}
else {
printf("Parent: Waiting to acquire semaphore\n");
sem_wait(&sem);
printf("Parent acquires lock\n");
read(pfds[0],buff,6); /* we don't need this */
printf("Parent read: %s",buff);
printf("parent releases lock\n");
sem_post(&sem);
}
sem_destroy(&sem);
return 0;
}
上面是我创建的一个简单管道,孩子在其中写入,父母在其中读取。我已经把一个信号量变量初始化为 1,所以当孩子写的时候,父母应该等待。添加了故意的“睡眠”,以便查看旋转“父:等待获取信号量”的父进程被打印。
The expected sequence should be:
Child: Waiting to acquire semaphore
child acquires lock...(delay of 5 secs here)
child releases lock
Parent: Waiting to acquire semaphore
Parent acquires lock
Parent read..bla-bla
parent releases lock
However it happens:
[root@localhost interview]# ./a.out
Child: Waiting to acquire semaphore
child acquires lock
Parent: Waiting to acquire semaphore
Parent acquires lock -> NOTE: Parent acquires lock before child releases it
child releases lock
Parent read: Hello
parent releases lock
问题是:当孩子延迟并仍然持有它并且尚未释放信号量时,父母为什么会获得锁?
另外,有什么方法可以确保孩子总是首先获得信号量,因为它应该写入管道?
编辑:感谢@jxh。这是修改后的代码,效果很好(粘贴供大家参考)。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/mman.h>
int main(void)
{
int pfds[2];
char buff[20];
sem_t *sem = mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_ANONYMOUS, -1, 0);
sem_init(sem, 1, 0);
pipe(pfds);
if (!fork()) {
write(pfds[1], "Hello", 6); /* make stdout same as pfds[1] */
close(pfds[0]); /* we don't need this */
printf("child releases semaphore\n");
sem_post(sem);
}
else {
printf("Parent: Waiting to acquire semaphore\n");
sem_wait(sem);
printf("Parent acquires lock\n");
read(pfds[0],buff,6); /* we don't need this */
printf("Parent read: %s\n",buff);
printf("parent releases lock\n");
sem_post(sem);
}
sem_destroy(sem);
return 0;
}