#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, так что, пока ребенок пишет, родитель должен ждать. Добавлен умышленный «сон», чтобы увидеть, что печатается родительский процесс, вращающийся «Родитель: Ожидание получения семафора».POSIX Семафор: Почему родительский процесс получает семафор до того, как его освободит?
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:
[[email protected] 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
Вопрос: Каким образом родитель получает блокировку в то время как ребенок задерживается и до сих пор держит его, и еще не выпустили семафора?
Кроме того, есть ли способ убедиться, что ребенок всегда сначала приобретает семафор, так как он должен писать в трубу?
EDIT: Благодаря @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;
}
Но как же родитель приобретает блокировку до того, как ребенок выпустит ее? Странно – kingsmasher1
@ kingsmasher1: Ваш родитель и ребенок участвуют в гонке за приобретение семафора одновременно. Это не то, что вы хотите. Инициализируйте семафор на '0' вместо этого, чтобы родительский блок заблокировал ожидание для дочернего элемента. Удалите вызов из 'sem_wait()' из дочернего элемента. – jxh
Я расскажу интересную вещь. Вы знаете, тот же код, просто инициализирующий семафор до «0», приводит к взаимоблокировке. И родительский, и детский отпечатки: «Ожидание приобретения ..» и продолжает ждать :-) – kingsmasher1