分叉的子进程是否使用相同的信号量?

2024-10-23 08:47:00
admin
原创
202
摘要:问题描述:假设我创建了一个信号量。如果我派生出一堆子进程,它们是否还会使用同一个信号量?另外,假设我创建一个包含信号量的结构并分叉。所有子进程是否仍使用相同的信号量?如果不是,将该结构+信号量存储在共享内存中是否会允许子进程使用相同的信号量?我真的很困惑我分叉的子进程如何使用相同的信号量。解决方案 1:假设我...

问题描述:

假设我创建了一个信号量。如果我派生出一堆子进程,它们是否还会使用同一个信号量?

另外,假设我创建一个包含信号量的结构并分叉。所有子进程是否仍使用相同的信号量?如果不是,将该结构+信号量存储在共享内存中是否会允许子进程使用相同的信号量?

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


解决方案 1:

假设我创建了一个信号量。如果我派生出一堆子进程,它们是否还会使用同一个信号量?

如果您使用的是 SysV IPC 信号量 ( semctl),那么可以。如果您使用的是 POSIX 信号量 ( sem_init),那么可以,但前提是您在创建时为 pshared 参数传递一个真值并将其放在共享内存中。

另外,假设我创建一个包含信号量的结构并分叉。所有子进程是否仍使用相同的信号量?如果不是,将该结构+信号量存储在共享内存中是否会允许子进程使用相同的信号量?

您所说的“内部信号量”是什么意思?对 SysV IPC 信号量的引用将被共享,因为信号量不属于任何进程。如果您使用 POSIX 信号量,或者使用 pthreads 互斥量和条件变量构建某些东西,则需要使用共享内存和 pshared 属性(pthreads也具有条件变量和互斥量的 pshared 属性)

请注意,使用该标志创建的匿名 mmapMAP_SHARED在这些用途中计为(匿名)共享内存,因此无需实际创建命名的共享内存段。普通堆内存在 fork 之后不会被共享

解决方案 2:

假设我创建了一个信号量。如果我派生出一堆子进程,它们是否还会使用同一个信号量?

这取决于您如何创建信号量,要使用 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
", 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
", i);
      if (sem_wait(sema) < 0) {
        perror("sem_wait");
      }
      printf("parent finished waiting: %d
", 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 中的信号量,但请注意,给出的跨 fork 的 UNIX 信号量示例不起作用,因为作者忘记使用MAP_ANONYMOUS中的标志mmap

解决方案 3:

尝试一下

子级和父级将交替增加共享变量

#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
", 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
", testptr->temp++);
    sem_post(&(testptr->mutex2));
  }
  exit(0);
}
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用