分叉的subprocess使用相同的信号量吗?
比方说,我创build一个信号量。 如果我分叉一堆subprocess,他们都会使用相同的信号量吗?
另外,假设我在里面创build了一个带有信号量的分叉结构。 所有的subprocess仍然使用相同的信号量吗? 如果没有,将存储结构+信号量共享内存允许subprocess使用相同的信号量?
我真的很困惑如何我的分叉subprocess可以使用相同的信号量。
比方说,我创build一个信号量。 如果我分叉一堆subprocess,他们都会使用相同的信号量吗?
如果你正在使用SysV IPC信号量( semctl
),那么是的。 如果你正在使用POSIX信号量( sem_init
),那么是的,但只有当你在创buildpshared参数时传递一个真实值并将其放在共享内存中。
另外,假设我在里面创build了一个带有信号量的分叉结构。 所有的subprocess仍然使用相同的信号量吗? 如果没有,将存储结构+信号量共享内存允许subprocess使用相同的信号量?
你是什么意思是“里面的信号灯”? 对SysV IPC信号量的引用将被共享,因为信号量不属于任何进程。 如果你正在使用POSIX信号量,或者使用pthreads互斥体和condvars来构造某些东西,那么你将需要使用共享内存和pshared属性(pthreads也有一个针对condvars和mutex的pshared属性)
请注意,使用MAP_SHARED
标志创build的匿名mmaps作为(匿名)共享内存用于这些目的,因此不必实际创build指定的共享内存段。 普通的堆内存不会在分叉之后共享 。
比方说,我创build一个信号量。 如果我分叉一堆subprocess,他们都会使用同一个信号量吗?
这取决于你如何创build信号量,用IPC信号量做到这一点,请参阅semaphore.c:示例传递简单信号量的插图 。
另外,假设我在里面创build了一个带有信号量的分叉结构。 所有的subprocess仍然使用相同的信号量吗? 如果没有,将存储结构+信号量共享内存允许subprocess使用相同的信号量?
为了实现这个function,你的信号量需要存储在父进程和subprocess之间共享的区域中,比如共享内存,而不是只在堆栈或堆上创build,因为当进程分叉时会被复制。
我真的很困惑如何我的分叉subprocess可以使用相同的信号量。
信号量可以跨线程或进程共享。 跨进程共享是在操作系统级别上实现的。 两个或多个不同的进程可以共享相同的信号量,即使这些进程不是通过派生单个父进程而创build的。
看到这个例子在父进程和它的subprocess之间共享一个未命名的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
标志。
尝试这个
孩子和父母会交替增加共享variables
#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); }