我想派生多个进程,然后在它们上使用一个信号灯。这是我尝试过的:
sem_init(&sem, 1, 1); /* semaphore*, pshared, value */
.
.
.
if(pid != 0){ /* parent process */
wait(NULL); /* wait all child processes */
printf("\nParent: All children have exited.\n");
.
.
/* cleanup semaphores */
sem_destroy(&sem);
exit(0);
}
else{ /* child process */
sem_wait(&sem); /* P operation */
printf(" Child(%d) is in critical section.\n",i);
sleep(1);
*p += i%3; /* increment *p by 0, 1 or 2 based on i */
printf(" Child(%d) new value of *p=%d.\n",i,*p);
sem_post(&sem); /* V operation */
exit(0);
}
输出为:
孩子(0)分叉
孩子(1)分叉
Child(0)在关键部分。
Child(1)在关键部分。
孩子(2)分叉
Child(2)在关键部分。
孩子(3)分叉
Child(3)在关键部分。
孩子(4)分叉
Child(4)在关键部分。
Child(0)新值* p = 0。
Child(1)新值* p = 1。
Child(2)的新值* p = 3。
Child(3)的新值* p = 3。
Child(4)的新值* p = 4。
父母:所有孩子都退出了。
显然,这意味着信号灯没有按预期的方式工作。您能解释一下我应该如何在分支进程中使用信号量?
您面临的问题是对sem_init()
功能的误解。阅读手册页时, 您将看到以下内容:
pshared参数指示此信号量是在进程的线程之间还是在进程之间共享。
如果您到此为止都读完了,您将认为pshared的非零值将使信号量成为进程间信号量。但是,这是错误的。您应该继续阅读,您将了解到必须在共享内存区域中找到信号灯。为此,可以使用几个功能,如下所示:
如果pshared为非零,则信号量在进程之间共享,并且应位于共享内存的区域中(请参见shm_open(3),mmap(2)和shmget(2))。(由于fork(2)创建的子级继承了其父级的内存映射,因此它也可以访问该信号量。)任何可以访问共享内存区域的进程都可以使用sem_post(3),sem_wait(3)等对该信号量进行操作。
。
我发现这种方法比其他方法更为复杂,因此我想鼓励人们使用sem_open()
而不是sem_init()
。
在下面您可以看到一个完整的程序,说明了以下内容:
如何派生多个进程并使父级等待所有子级退出。
int main (int argc, char argv){
int i; /
loop variables /
key_t shmkey; / shared memory key /
int shmid; / shared memory id /
sem_t sem; / synch semaphore //shared /
pid_t pid; / fork pid /
int p; / shared variable //shared /
unsigned int n; / fork count /
unsigned int value; / semaphore value /
/* initialize a shared variable in shared memory */
shmkey = ftok ("/dev/null", 5); /* valid directory name and a number */
printf ("shmkey for p = %d\n", shmkey);
shmid = shmget (shmkey, sizeof (int), 0644 | IPC_CREAT);
if (shmid < 0){ /* shared memory error check */
perror ("shmget\n");
exit (1);
}
p = (int *) shmat (shmid, NULL, 0); /* attach p to shared memory */
*p = 0;
printf ("p=%d is allocated in shared memory.\n\n", *p);
/********************************************************/
printf ("How many children do you want to fork?\n");
printf ("Fork count: ");
scanf ("%u", &n);
printf ("What do you want the semaphore value to be?\n");
printf ("Semaphore value: ");
scanf ("%u", &value);
/* initialize semaphores for shared processes */
sem = sem_open ("pSem", O_CREAT | O_EXCL, 0644, value);
/* name of semaphore is "pSem", semaphore is reached using this name */
printf ("semaphores initialized.\n\n");
/* fork child processes */
for (i = 0; i < n; i++){
pid = fork ();
if (pid < 0) {
/* check for error */
sem_unlink ("pSem");
sem_close(sem);
/* unlink prevents the semaphore existing forever */
/* if a crash occurs during the execution */
printf ("Fork error.\n");
}
else if (pid == 0)
break; /* child processes */
}
/******************************************************/
/****************** PARENT PROCESS ****************/
/******************************************************/
if (pid != 0){
/* wait for all children to exit */
while (pid = waitpid (-1, NULL, 0)){
if (errno == ECHILD)
break;
}
printf ("\nParent: All children have exited.\n");
/* shared memory detach */
shmdt (p);
shmctl (shmid, IPC_RMID, 0);
/* cleanup semaphores */
sem_unlink ("pSem");
sem_close(sem);
/* unlink prevents the semaphore existing forever */
/* if a crash occurs during the execution */
exit (0);
}
/******************************************************/
/****************** CHILD PROCESS *****************/
/******************************************************/
else{
sem_wait (sem); /* P operation */
printf (" Child(%d) is in critical section.\n", i);
sleep (1);
*p += i % 3; /* increment *p by 0, 1 or 2 based on i */
printf (" Child(%d) new value of *p=%d.\n", i, *p);
sem_post (sem); /* V operation */
exit (0);
}
}
输出值
./a.out
shmkey for p = 84214791
p=0 is allocated in shared memory.
How many children do you want to fork?
Fork count: 6
What do you want the semaphore value to be?
Semaphore value: 2
semaphores initialized.
Child(0) is in critical section.
Child(1) is in critical section.
Child(0) new value of *p=0.
Child(1) new value of *p=1.
Child(2) is in critical section.
Child(3) is in critical section.
Child(2) new value of *p=3.
Child(3) new value of *p=3.
Child(4) is in critical section.
Child(5) is in critical section.
Child(4) new value of *p=4.
Child(5) new value of *p=6.
Parent: All children have exited.
检查还不错,shmkey
因为ftok()
失败时返回-1。但是,如果您有多个共享变量,并且ftok()
函数多次失败,则具有shmkey
with值的共享变量-1
将驻留在共享内存的同一区域中,从而导致一个更改影响另一个。因此,程序执行将变得混乱。为了避免这种情况,最好检查是否ftok()
返回-1(最好是签入源代码,而不是像我一样打印到屏幕上,尽管我想向您显示键值以防发生冲突)。
请注意如何声明和初始化信号量。它与您在问题(sem_t sem
vs sem_t* sem
)中所做的不同。此外,您应该使用它们在本示例中显示的形式。您不能在中定义sem_t*
和使用它sem_init()
。
这显然意味着信号量没有正常工作。你能解释一下我应该如何在分叉进程上使用信号量吗?
问题内容: 假设我创建了一个信号量。如果我派生了一堆子进程,它们还会使用相同的信号量吗? 另外,假设我创建了一个内部带有信号灯并分叉的结构。所有子进程仍然使用相同的信号量吗?如果不是,将struct + semaphores存储在共享内存中是否允许子进程使用相同的信号量? 我对派生的子进程如何使用相同的信号量感到非常困惑。 问题答案: 假设我创建了一个信号量。如果我派生了一堆子进程,它们还会使用相
我有多个进程与Sempahore同步。我知道这段代码不允许gurantee出现这样的情况:在sem_getvalue期间,即使值变为零,甚至在调用特定进程中的sem_post之前,anotehr进程也可能调用sem_post,使值变为2。如何解决这种情况。 我的问题不能通过互斥体来解决,在我的问题中,有些进程只用于信号,即操作,而在互斥体中,所有进程都将等待并不断地发出信号
null
这个问题要求使用两个信号量,一个作为互斥量,一个作为计数信号量,并使用这两个信号量来模拟学生和教师助手之间的交互。 我已经能够很容易地使用二进制信号量,但是我似乎找不到很多例子来说明计数信号量的使用,所以我很确定我错了,这导致我的代码不能正确执行。 我的代码如下 我的主要问题是:如何让线程同时轮询计数信号量? 我正试图获得备份,一些学生被迫离开(或退出线程),而其他人则在信号量中等待。任何帮助都是
我只能在线程之间使用它,但我想在进程之间共享。所以我的问题是,如何使用posix计数信号量来制作二进制信号量?