您面临的问题是对
sem_init()功能的误解。阅读手册页时, 您将看到以下内容:
pshared参数指示此信号量是在进程的线程之间还是在进程之间共享。
如果您到此为止都读完了,您将认为pshared的非零值将使信号量成为进程间信号量。但是,这是错误的。您应该继续阅读,您将了解到必须在共享内存区域中找到信号灯。为此,可以使用几个功能,如下所示:
如果pshared为非零,则信号量在进程之间共享,并且应位于共享内存的区域中(请参见shm_open(3),mmap(2)和shmget(2))。(由于fork(2)创建的子级继承了其父级的内存映射,因此它也可以访问该信号量。)任何可以访问共享内存区域的进程都可以使用sem_post(3),sem_wait(3)等对该信号量进行操作。
。
我发现这种方法比其他方法更为复杂,因此我想鼓励人们使用
sem_open()而不是
sem_init()。
在下面您可以看到一个完整的程序,说明了以下内容:
- 如何在派生的进程之间分配共享内存和使用共享变量。
- 如何在共享内存区域中初始化信号量,并由多个进程使用。
如何派生多个进程并使父级等待所有子级退出。
include
/ printf() / include
/ exit(), malloc(), free() / include
/ key_t, sem_t, pid_t / include
/ shmat(), IPC_RMID / include
/ errno, ECHILD / include
/ sem_open(), sem_destroy(), sem_wait().. / include
/ O_CREAT, O_EXEC / 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 /shmkey = ftok ("/dev/null", 5); printf ("shmkey for p = %dn", shmkey);shmid = shmget (shmkey, sizeof (int), 0644 | IPC_CREAT);if (shmid < 0){ perror ("shmgetn"); exit (1);}p = (int *) shmat (shmid, NULL, 0); *p = 0;printf ("p=%d is allocated in shared memory.nn", *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);sem = sem_open ("pSem", O_CREAT | O_EXCL, 0644, value); printf ("semaphores initialized.nn");for (i = 0; i < n; i++){ pid = fork (); if (pid < 0) { sem_unlink ("pSem");sem_close(sem); printf ("Fork error.n"); } else if (pid == 0) break; }if (pid != 0){ while (pid = waitpid (-1, NULL, 0)){ if (errno == ECHILD) break; } printf ("nParent: All children have exited.n"); shmdt (p); shmctl (shmid, IPC_RMID, 0); sem_unlink ("pSem"); sem_close(sem); exit (0);}else{ sem_wait (sem); printf (" Child(%d) is in critical section.n", i); sleep (1); *p += i % 3; printf (" Child(%d) new value of *p=%d.n", i, *p); sem_post (sem); exit (0);}}
输出值
./a.out shmkey for p = 84214791p=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: 2semaphores 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()函数多次失败,则具有
shmkeywith值的共享变量
-1将驻留在共享内存的同一区域中,从而导致一个更改影响另一个。因此,程序执行将变得混乱。为了避免这种情况,最好检查是否
ftok()
返回-1(最好是签入源代码,而不是像我一样打印到屏幕上,尽管我想向您显示键值以防发生冲突)。
请注意如何声明和初始化信号量。它与您在问题(
sem_t semvs
sem_t*sem)中所做的不同。此外,您应该使用它们在本示例中显示的形式。您不能在中定义
sem_t*和使用它
sem_init()。



