分叉的subprocess使用相同的信号量吗?

比方说,我创build一个信号量。 如果我分叉一堆subprocess,他们都会使用同一个信号量吗?

另外,假设我在里面创build了一个带有信号量的分叉结构。 所有的subprocess仍然使用相同的信号量吗? 如果没有,将存储结构+信号量共享内存允许subprocess使用相同的信号量?

我真的很困惑如何我的分叉subprocess可以使用相同的信号量。

Solutions Collecting From Web of "分叉的subprocess使用相同的信号量吗?"

比方说,我创建一个信号量。 如果我分叉一堆子进程,他们都会使用同一个信号量吗?

如果你正在使用SysV IPC信号量( semctl ),那么是的。 如果你正在使用POSIX信号量( sem_init ),那么是的,但只有当你在创建pshared参数时传递一个真实的值并将它放在共享内存中。

另外,假设我在里面创建了一个带有信号量的分叉结构。 所有的子进程仍然使用相同的信号量吗? 如果没有,将存储结构+信号量共享内存允许子进程使用相同的信号量?

你是什​​么意思是“里面的信号灯”? 对SysV IPC信号量的引用将被共享,因为信号量不属于任何进程。 如果你正在使用POSIX信号量,或者使用pthreads互斥体和condvars来构造某些东西,那么你将需要使用共享内存和pshared属性(pthreads也有一个针对condvars和mutex的pshared属性)

请注意,使用MAP_SHARED标志创建的匿名mmaps作为(匿名)共享内存用于这些目的,因此不必实际创建指定的共享内存段。 普通的堆内存不会在分叉之后共享

比方说,我创建一个信号量。 如果我分叉一堆子进程,他们都会使用相同的信号量吗?

这取决于你如何创建信号量,用IPC信号量做到这一点,请参阅semaphore.c:示例传递简单信号量的插图 。

另外,假设我在里面创建了一个带有信号量的分叉结构。 所有的子进程仍然使用相同的信号量吗? 如果没有,将存储结构+信号量共享内存允许子进程使用相同的信号量?

为了达到这个目的,你的信号量需要存储在父进程和子进程之间共享的区域中,比如共享内存,而不是仅仅在堆栈或堆上创建,因为当进程分叉时会被复制。

我真的很困惑如何我的分叉子进程可以使用相同的信号量。

信号量可以跨线程或进程共享。 跨进程共享是在操作系统级别上实现的。 两个或多个不同的进程可以共享相同的信号量,即使这些进程不是通过派生单个父进程而创建的。

看到这个例子在父进程和它的子进程之间共享一个未命名的UNIX信号量(用gcc编译,你将需要-pthread标志):

 #include <semaphore.h> #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> int main(void) { /* place semaphore in shared memory */ sem_t *sema = mmap(NULL, sizeof(*sema), PROT_READ |PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS, -1, 0); if (sema == MAP_FAILED) { perror("mmap"); exit(EXIT_FAILURE); } /* create/initialize semaphore */ if ( sem_init(sema, 1, 0) < 0) { perror("sem_init"); exit(EXIT_FAILURE); } int nloop=10; int pid = fork(); if (pid < 0) { perror("fork"); exit(EXIT_FAILURE); } if (pid == 0) { /* child process*/ for (int i = 0; i < nloop; i++) { printf("child unlocks semaphore: %d\n", i); if (sem_post(sema) < 0) { perror("sem_post"); } sleep(1); } if (munmap(sema, sizeof(sema)) < 0) { perror("munmap"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } if (pid > 0) { /* back to parent process */ for (int i = 0; i < nloop; i++) { printf("parent starts waiting: %d\n", i); if (sem_wait(sema) < 0) { perror("sem_wait"); } printf("parent finished waiting: %d\n", i); } if (sem_destroy(sema) < 0) { perror("sem_destroy failed"); exit(EXIT_FAILURE); } if (munmap(sema, sizeof(sema)) < 0) { perror("munmap failed"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } } 

输出将是:

 parent starts waiting: 0 child unlocks semaphore: 0 parent finished waiting: 0 parent starts waiting: 1 child unlocks semaphore: 1 parent finished waiting: 1 ... 

您也可以在Linux中阅读Semaphores ,但请注意,给定跨叉的UNIX信号示例不起作用,因为作者忘记了在mmap使用MAP_ANONYMOUS标志。

尝试这个

孩子和父母会交替增加共享变量

 #include <semaphore.h> #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> struct test { sem_t mutex1; sem_t mutex2; int temp; }test1; int main(int argc, char **argv) { int fd, i,count=0,nloop=10,zero=0,*ptr; struct test *testptr; //open a file and map it into memory sem_t mutex; fd = open("log.txt",O_RDWR|O_CREAT,S_IRWXU); write(fd,&zero,sizeof(int)); ptr = mmap(NULL, sizeof(struct test),PROT_READ |PROT_WRITE,MAP_SHARED,fd,0); close(fd); memcpy(ptr, &test1, sizeof(test1)); testptr = (struct test *)ptr; // testptr = (struct test *)&test1; /* create, initialize semaphore */ if( sem_init(&(testptr->mutex1),1,1) < 0) { perror("semaphore initilization"); exit(0); } /* create, initialize semaphore */ if( sem_init(&(testptr->mutex2),1,0) < 0) { perror("semaphore initilization"); exit(0); } if (fork() == 0) { /* child process*/ for (i = 0; i < nloop; i++) { sem_wait(&(testptr->mutex2)); printf("child: %d\n", testptr->temp++); sem_post(&(testptr->mutex1)); } exit(0); /* back to parent process */ for (i = 0; i < nloop; i++) { sem_wait(&testptr->mutex1); printf("parent: %d\n", testptr->temp++); sem_post(&(testptr->mutex2)); } exit(0); }