В родительском процессе создание объекта семафора только с одним семафором.Инициализация семафора в начальное значение ноль (0).Выполнение операции декремента в дочернем процессе и операции инкремента в родительском процессе.
Начальное значение - 0 Родитель - Приращение (1) Дочерний - Декремент (0)
Здесь я хочу спатьparent в течение некоторого времени, так что child ожидает уменьшения значения семафора до тех пор, пока parent не увеличит его до 1.
В parent я поместил sleep (10) и дал первому исполнению child семафор декремента, чтобы child ждал до 10 sec, покаparent увеличивает семафор.
Для этого я попробовал два разных подхода для реализации semop () (с IPC_NOWAIT и DEFAULT) в дочернем процессе, и я предоставлю код для обоих подходов.Я не понимаю, почему эти два подхода ведут себя по-разному, поскольку они должны давать одинаковое поведение.
Первый подход с использованием IPC_NOWAIT:
#include<sys/ipc.h>
#include<sys/sem.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#define KEY1 12345
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
int main()
{
int ret1,ret, sem, id2;
union semun u1;
struct sembuf sboa,sb;
int status;
sem = semget(KEY1, 1, IPC_CREAT|0600);
if(sem<0) { perror("error in semaphore creation"); exit(1); }
u1.val = 0;
ret1=semctl(sem,0,SETVAL,u1);
ret1 = semctl(sem,0,GETVAL);
printf("Initial value of sem - %d\n",ret1);
ret= fork();
if(ret<0)
{
perror("error in chid");
exit(1);
}
if(ret==0)
{
//sleep(1);
int x;
ret1 = semctl(sem,0,GETVAL);
printf("child.....before decrement..the value of sem - %d\n",ret1);
sboa.sem_num = 0;
sboa.sem_op = -1;
sboa.sem_flg = IPC_NOWAIT;
while ((x = semop(sem, &sboa, 1) < 0))
{
if (errno == EAGAIN)
{
//printf("Not able to get semaphore, received EAGAIN error\n");
//printf("child.....before decrement..the value of sem - %d\n",ret1);
sleep(1); continue;
}
else
{
perror("exiting now from child as not able to do semop:");
break;
}
}
ret1 = semctl(sem,0,GETVAL);
printf("child.....after decrement..the value of sem - %d\n",ret1);
exit(0);
}
if(ret>0)
{
int x;
ret1 = semctl(sem,0,GETVAL);
printf("parent.....before increment..the value of sem - %d\n",ret1);
sleep(10);
sboa.sem_num = 0;
sboa.sem_op = +1;
sboa.sem_flg = 0;
semop(sem,&sboa, 1);
ret1 = semctl(sem,0,GETVAL);
printf("parent....after increment ..the value of sem - %d\n",ret1);
}
ret = waitpid(-1,&status,0);
if(ret > 0 )
{
printf("Child with the id: %d terminated\n", ret);
if(WIFEXITED(status))
{
printf("Process exited normally\n");
}
else
{
printf("Process exited abnormally");
}
}
else
{
perror("Error in executing waitpid\n");
exit(1);
}
semctl(sem,0,IPC_RMID);
return(0);
}
// ВЫХОД с IPC_NOWAIT
Initial value of sem - 0
parent.....before increment..the value of sem - 0
child.....before decrement..the value of sem - 0
parent....after increment ..the value of sem - 1
child.....after decrement..the value of sem - 0
Child with the id: 10284 terminated
Process exited normally
Второй подход с использованием по умолчанию:
#include<sys/ipc.h>
#include<sys/sem.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#define KEY1 12345
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
int main()
{
int ret1,ret, sem, id2;
union semun u1;
struct sembuf sboa,sb;
int status;
sem = semget(KEY1, 1, IPC_CREAT|0600);
if(sem<0) { perror("error in semaphore creation"); exit(1); }
u1.val = 0;
ret1=semctl(sem,0,SETVAL,u1);
ret1 = semctl(sem,0,GETVAL);
printf("Initial value of sem - %d\n",ret1);
ret= fork();
if(ret<0)
{
perror("error in chid");
exit(1);
}
if(ret==0)
{
int x;
ret1 = semctl(sem,0,GETVAL);
printf("child.....before decrement..the value of sem - %d\n",ret1);
sboa.sem_num = 0;
sboa.sem_op = -1;
sboa.sem_flg = 0;
semop(sem, &sboa, 1);
ret1 = semctl(sem,0,GETVAL);
printf("child.....after decrement..the value of sem - %d\n",ret1);
exit(0);
}
if(ret>0)
{
int x;
ret1 = semctl(sem,0,GETVAL);
printf("parent.....before increment..the value of sem - %d\n",ret1);
sleep(10);
sboa.sem_num = 0;
sboa.sem_op = +1;
sboa.sem_flg = 0;
semop(sem,&sboa, 1);
ret1 = semctl(sem,0,GETVAL);
printf("parent....after increment ..the value of sem - %d\n",ret1);
}
ret = waitpid(-1,&status,0);
if(ret > 0 )
{
printf("Child with the id: %d terminated\n", ret);
if(WIFEXITED(status))
{
printf("Process exited normally\n");
}
else
{
printf("Process exited abnormally");
}
}
else
{
perror("Error in executing waitpid\n");
exit(1);
}
semctl(sem,0,IPC_RMID);
return(0);
}
// ВЫХОД с использованием DEFAULT
Initial value of sem - 0
parent.....before increment..the value of sem - 0
child.....before decrement..the value of sem - 0 --> after this the child should have blocked for 10 sec but it continued to print next line
child.....after decrement..the value of sem - 0 --> this line should have printed after 10 sec, how could child get to this line before decrementing semaphore??
parent....after increment ..the value of sem - 1
Child with the id: 10261 terminated
Process exited normally
Таким образом, при подходе DEFAULT semop () должен ждать, пока родительский процесс примет значение семафора1 но это не так, ПОЧЕМУ?Я использовал IPC_NOWAIT для реализации semop (). Должны ли мы всегда использовать этот подход?Каков лучший / рекомендуемый способ реализации semop () для такого рода проблем?ПРИМЕЧАНИЕ. Для справки используйте оба фрагмента кода.