在父进程中创建仅包含一个信号量的信号量对象。将信号量初始化为初始值零(0)。 在子进程中执行递减操作,在父进程中执行递增操作。
初始值-0 父级-增量(1) 儿童-减量(0)
在这里我想让父母睡觉一段时间,以便孩子等待信号量值递减,直到父母将其增加到1。
在父母中,我放置sleep(10)并让孩子第一次执行以减少信号量,因此孩子要等10秒钟,直到父母增加信号量为止。
为此,我尝试了两种不同的方法在子进程中实现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);
}
//使用默认值输出
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(),我们应该始终使用这种方法吗? 解决此类问题的最佳方法/推荐方法是什么? 注意:请同时使用两个代码段作为参考。