Linux 分叉的子进程是否使用相同的信号量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6847973/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Do forked child processes use the same semaphore?
提问by jmnwong
Let's say I create a semaphore. If I fork a bunch of child processes, will they all still use that same semaphore?
假设我创建了一个信号量。如果我 fork 一堆子进程,它们是否仍然使用相同的信号量?
Also, suppose I create a struct with semaphores inside and forked. Do all the child processes still use that same semaphore? If not, would storing that struct+semaphores in shared memory allow the child processes to use the same semaphores?
另外,假设我创建了一个内部带有信号量并分叉的结构。所有子进程是否仍然使用相同的信号量?如果没有,将结构+信号量存储在共享内存中是否允许子进程使用相同的信号量?
I'm really confused about how my forked child processes can use the same semaphores.
我真的很困惑我的分叉子进程如何使用相同的信号量。
采纳答案by bdonlan
Let's say I create a semaphore. If I fork a bunch of child processes, will they all still use that same semaphore?
假设我创建了一个信号量。如果我 fork 一堆子进程,它们是否仍然使用相同的信号量?
If you are using a SysV IPC semaphore (semctl
), then yes. If you are using POSIX semaphores (sem_init
), then yes, but only if you pass a true value for the pshared argumenton creation and place it in shared memory.
如果您使用的是 SysV IPC 信号量 ( semctl
),则可以。如果您使用 POSIX 信号量 ( sem_init
),则可以,但前提是您在创建时为 pshared 参数传递了一个真值并将其放置在共享内存中。
Also, suppose I create a struct with semaphores inside and forked. Do all the child processes still use that same semaphore? If not, would storing that struct+semaphores in shared memory allow the child processes to use the same semaphores?
另外,假设我创建了一个内部带有信号量并分叉的结构。所有子进程是否仍然使用相同的信号量?如果没有,将结构+信号量存储在共享内存中是否允许子进程使用相同的信号量?
What do you mean be 'semaphores inside'? References to SysV IPC semaphores will be shared, because the semaphores don't belong to any process. If you're using POSIX semaphores, or constructing something out of pthreads mutexes and condvars, you will need to use shared memory, and the pshared attribute (pthreads has a pshared attribute for condvarsand mutexesas well)
你是什么意思是“里面的信号量”?对 SysV IPC 信号量的引用将被共享,因为信号量不属于任何进程。如果您正在使用 POSIX 信号量,或者从 pthreads 互斥体和 condvars 构建某些东西,您将需要使用共享内存和 pshared 属性(pthreads 也有一个用于condvars和互斥体的 pshared 属性)
Note that anonymous mmaps created with the MAP_SHARED
flag count as (anonymous) shared memory for these purposes, so it's not necessary to actually create a named shared memory segment. Ordinary heap memory will not be shared after a fork.
请注意,MAP_SHARED
出于这些目的,使用标志创建的匿名 mmap计为(匿名)共享内存,因此实际上没有必要创建命名共享内存段。普通堆内存不会在 fork 后共享。
回答by jmnwong
Let's say I create a semaphore. If I fork a bunch of child processes, will they all still use that same semaphore?
假设我创建了一个信号量。如果我 fork 一堆子进程,它们是否仍然使用相同的信号量?
It depends how you created the semaphore, to do that with an IPC semaphore see semaphore.c: Illustration of simple semaphore passingfor an example.
这取决于您如何创建信号量,要使用 IPC 信号量来实现,请参见semaphore.c: 简单信号量传递示例的说明。
Also, suppose I create a struct with semaphores inside and forked. Do all the child processes still use that same semaphore? If not, would storing that struct+semaphores in shared memory allow the child processes to use the same semaphores?
另外,假设我创建了一个内部带有信号量并分叉的结构。所有子进程是否仍然使用相同的信号量?如果没有,将结构+信号量存储在共享内存中是否允许子进程使用相同的信号量?
For that to work your semaphore needs to be stored in an area shared between the parent and the child process like shared memory, and not just created on the stack or on the heap because it will be copied when the process forks.
为此,您的信号量需要存储在父进程和子进程之间共享的区域中,例如共享内存,而不仅仅是在堆栈或堆上创建,因为它会在进程分叉时被复制。
I'm really confused about how my forked child processes can use the same semaphores.
我真的很困惑我的分叉子进程如何使用相同的信号量。
The semaphore can be shared across threads or processes. Cross-process sharing is implemented on the operating system level. Two or more different processes can share the same semaphore even if those processes were not created by forking a single parent process.
信号量可以跨线程或进程共享。跨进程共享是在操作系统层面实现的。两个或多个不同的进程可以共享相同的信号量,即使这些进程不是通过派生单个父进程创建的。
See this example for sharing an unnamed UNIX semaphore between a parent process and its child (to compile with gcc you'll need the -pthread
flag):
请参阅此示例以在父进程与其子进程之间共享未命名的 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);
}
}
The output will be:
输出将是:
parent starts waiting: 0
child unlocks semaphore: 0
parent finished waiting: 0
parent starts waiting: 1
child unlocks semaphore: 1
parent finished waiting: 1
...
You may want to read Semaphores in Linuxas well, but be aware that the example of UNIX semaphores across fork given doesn't work because the author forgot to use the MAP_ANONYMOUS
flag in mmap
.
您可能还想阅读Linux 中的信号量,但请注意,给出的跨 fork 的 UNIX 信号量示例不起作用,因为作者忘记MAP_ANONYMOUS
在mmap
.
回答by user997487
Try this
尝试这个
child and parent would increment the shared variable alternatively
child 和 parent 将交替增加共享变量
#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);
}