Используют ли разветвленные дочерние процессы один и тот же семафор? - PullRequest
7 голосов
/ 27 июля 2011

Допустим, я создаю семафор. Если я разветвляю кучу дочерних процессов, все ли они будут использовать тот же семафор?

Также предположим, что я создаю структуру с семафорами внутри и разветвлен. Все ли дочерние процессы все еще используют один и тот же семафор? Если нет, хранение семафоров struct + в разделяемой памяти позволит дочерним процессам использовать те же семафоры?

Я действительно не понимаю, как мои разветвленные дочерние процессы могут использовать одни и те же семафоры.

Ответы [ 3 ]

10 голосов
/ 27 июля 2011

Допустим, я создаю семафор.Если я разветвляю несколько дочерних процессов, все ли они все еще будут использовать тот же семафор?

Если вы используете семафор SysV IPC (semctl), тогда да.Если вы используете семафоры POSIX (sem_init), то да, но только если вы передаете истинное значение для аргумента pshared при создании и помещаете его в общую память.

Также предположим, что я создаю структуру с семафорами внутри и разветвлен.Все ли дочерние процессы все еще используют один и тот же семафор?Если нет, хранение семафоров struct + в разделяемой памяти позволит дочерним процессам использовать те же семафоры?

Что вы подразумеваете под «семафорами внутри»?Ссылки на семафоры SysV IPC будут общими, потому что семафоры не принадлежат ни одному процессу.Если вы используете семафоры POSIX или создаете что-то из мьютексов и condvars pthreads, вам потребуется использовать разделяемую память и атрибут pshared (pthreads имеет атрибут pshared для condvars и mutexes также)

Обратите внимание, что анонимные карты, созданные с флагом MAP_SHARED, считаются (анонимной) разделяемой памятью для этих целей, поэтому нет необходимости фактически создавать именованный сегмент совместно используемой памяти. Обычная память кучи не будет распределена после разветвления .

7 голосов
/ 27 июля 2011

Допустим, я создаю семафор. Если я разветвляюсь кучу дочерних процессов, они все еще будут использовать тот же семафор?

Зависит от того, как вы создали семафор, чтобы сделать это с семафором IPC, см. semaphore.c: Иллюстрация простого семафора, передающего для примера.

Также предположим, что я создаю структуру с семафорами внутри и разветвлен. Делать все дочерние процессы все еще используют тот же семафор? Если нет, то будет хранение семафоров struct + в разделяемой памяти позволяет ребенку процессы используют одни и те же семафоры?

Для этого ваш семафор должен храниться в области, совместно используемой родительским и дочерним процессами, например, совместно используемой памяти, а не просто создаваться в стеке или в куче, потому что он будет скопирован, когда процесс разветвится. 1013 *

Я действительно не понимаю, как мои разветвленные дочерние процессы могут использовать те же семафоры.

Семафор можно разделить между потоками или процессами. Межпроцессное совместное использование реализовано на уровне операционной системы. Два или более разных процесса могут совместно использовать один и тот же семафор, даже если эти процессы не были созданы путем разветвления одного родительского процесса.

См. Этот пример для совместного использования безымянного семафора 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 , но имейте в виду, что пример семафоров UNIX для данной вилки не работает, поскольку автор забыл использовать флаг MAP_ANONYMOUS в mmap.

0 голосов
/ 29 октября 2011

Попробуйте это

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);
}
...