用于 IPC 的命名信号灯的 POSIX 实现



我正在做一项家庭作业,涉及实现信号量以强制子进程之间的互斥。我的大部分代码都在工作,除了我没有正确使用信号量。我找到的文章没有多大帮助。有人可以向我解释 POSIX 信号量的工作原理吗?

例如,如果我有一个父进程使用fork()execl()生成子进程:

sem=sem_open("/semaphore1",O_CREAT|O_EXCL,S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,1);
for (i = 0; i < 3; i++) 
{
//three child process are spawned in the image of the parent
child[i] = fork();
//establish whether all children were created successfully
switch (child[i]) 
{
//child process creation failed...
case -1:
rpterror ((char *)"fork failure", pname);
exit(1);
//given that the fork() was successful (the children were spawned successfully)...
case 0:
sprintf (pname, "shmc%d", i+1);
execl("shmc1", pname, ascshmid, (char *)0);
perror ("execl failed");
exit (2);
}
}

子项希望访问和修改共享内存段(由父级创建(中的值:

sem=sem_open("/semaphore1", O_RDWR);
while ( !all_out) 
{       /* loop to sell all seats */
/* puts the process to sleep for an amount of time, then decreases the amount of seats available. Before printing out the new count of seats, the process sleeps again. Finally, it prints the seat count until there are no more seats left.*/
if (class_ptr->seats_left > 0) 
{
sem_wait(sem);
sleep ( (unsigned)rand()%5 + 1);
class_ptr->seats_left--;
sleep ( (unsigned)rand()%5 + 1);
cout << pname << " SOLD SEAT -- "  << class_ptr->seats_left << " left" <<endl;
sem_post(sem);
}
else
{
all_out++;
cout << pname << " sees no seats left" << endl;
}
sleep ( (unsigned)rand()%10 + 1);
}

其中seats_left是共享变量。

运行此代码会给我一个如下所示的输出。共享变量的初始值为 15:

shmc1 SOLD SEAT -- 14 left
shmc2 SOLD SEAT -- 13 left
shmc3 SOLD SEAT -- 12 left
shmc1 SOLD SEAT -- 11 left
shmc2 SOLD SEAT -- 10 left
shmc3 SOLD SEAT -- 9 left
shmc1 SOLD SEAT -- 8 left
shmc2 SOLD SEAT -- 7 left
shmc3 SOLD SEAT -- 6 left
shmc2 SOLD SEAT -- 5 left
shmc1 SOLD SEAT -- 4 left
shmc3 SOLD SEAT -- 3 left
shmc2 SOLD SEAT -- 2 left
shmc1 SOLD SEAT -- 1 left
shmc1 sees no seats left
shmc3 SOLD SEAT -- 0 left
shmc3 sees no seats left
shmc2 SOLD SEAT -- -1 left
shmc2 sees no seats left
Parent removing shm

如您所见,最后是我的进程进入关键部分的地方,同时另一个进程正在这样做。有谁知道为什么会这样?

尝试将sem_wait()移到if语句之外:

sem=sem_open("/semaphore1", O_RDWR);
while (!all_out) {
sem_wait(sem);
if (class_ptr->seats_left > 0)  {
sleep((unsigned)rand()%5 + 1);
class_ptr->seats_left--;
sleep((unsigned)rand()%5 + 1);
cout << pname << " SOLD SEAT -- "  << class_ptr->seats_left << " left" <<endl;
}
else {
all_out++;
cout << pname << " sees no seats left" << endl;
}
sem_post(sem);
sleep((unsigned)rand()%10 + 1);
}

我不认为您对不尊重关键部分的流程有问题(尽管信号量是一种荣誉系统,就像常规的红绿灯一样......我认为问题只是进程B正在等待由进程A持有的锁,当A卖掉最后一张票并松开锁时,B抓住锁并出售另一张票,因为它已经检查了票是否可用,并且在出售最后一张票之前再也不会检查。

如果您运行足够多的次数,您可能会看到零、一和两张票证超售的情况。

最新更新