C - fork () и разделение памяти - PullRequest
13 голосов
/ 21 апреля 2010

Мне нужно, чтобы мой родительский и дочерний процессы могли читать и записывать одну и ту же переменную (типа int), поэтому она является "глобальной" между двумя процессами.

Я предполагаю, что это будет использовать какую-то межпроцессную коммуникацию и иметь одну переменную в одном обновляемом процессе.

Я быстро выполнил Google и IPC, и появились различные методы, но я не знаю, какой из них наиболее подходит для моей ситуации.

Итак, какая техника лучше, и не могли бы вы дать ссылку на учебник по noobs для нее.

Спасибо.

Ответы [ 3 ]

16 голосов
/ 21 апреля 2010

Поскольку вы упоминаете об использовании fork (), я предполагаю, что вы живете в * nix-System

С Unix.com

Основной способ обмена данными между процессы, использующие UNIX IPC:

(1) Общая память;

(2) Розетки:

Существуют и другие UNIX IPC, включая

(3) Очереди сообщений.

(4) семафоры;

(5) Сигналы.

Лучше всего (для IPC) использовать сегменты разделяемой памяти, основанные на сообщение. Возможно, вам придется использовать семафоры чтобы гарантировать, что общая память операции атомарные.

Учебник по разветвлению и общей памяти находится в разработке:

http://forums.devshed.com/c-programming-42/posix-semaphore-example-using-fork-and-shared-memory-330419.html

еще одно более подробное описание использования многопоточности (если применимо для вашего приложения) можно найти здесь:

https://computing.llnl.gov/tutorials/pthreads/

4 голосов
/ 21 апреля 2010

Если вам нужно разделить память, возможно, лучше использовать потоки вместо процессов?

2 голосов
/ 10 июня 2011

Один из вариантов совместной памяти, который я недавно использовал, - открыть mmap перед разветвлением. Это позволяет избежать определенных ограничений API общей памяти. У вас нет ограничения по размеру (диапазон адресов ограничен), вам не нужно генерировать ключ из этого абсолютного файла. Вот пример, как я это сделал (я упустил проверку ошибок для краткости)

ppid = getpid();
shm_size  = ...;

char *tmpFile = tempnam(NULL, "SHM_");    /* Generate a temp file which is virtual */

/* Before we fork, build the communication memory maps */
mm = open(tmpFile, O_RDWR|O_CREAT|O_TRUNC, 0664));    /* Create the temp file */
ftruncate(mm, shm_size);                              /* Size the file to the needed size, on modern Unices it's */
                                                      /* a sparse file which doesn't allocate anything in the file system */

/* The exact type of comm_area left to the implementer */
comm_area *pCom = (comm_area *)mmap(NULL, shm_size, PROT_READ|PROT_WRITE, MAP_SHARED, mm, 0);
if(pCom == (comm_area*)MAP_FAILED) handle_error();
close(mm);                                /* We can close the file, we won't access it via handle */
unlink(tmpFile);                          /* We can also remove the file so even if we crash we won't let corpses lying */
free(tmpFile);

/* Initialise some shared mutexes and semaphores */
pthread_mutexattr_t mattr;
pthread_mutexattr_init(&mattr);
pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&pCom->stderr_mutex, &mattr);         

/* nSonAsked, global variable with the number of forked processes asked */
for(nSon=0; nSon<nSonsAsked; nSon++) {

  printf("Setup son #%.2u ",nSon+1);
  /* Initialize a semaphore for each child process */
  sem_init(&pCom->sem_ch[nSon], USYNC_PROCESS, 0);
  if(fork() == 0 {
     ... /* do child stuff*/
     return;
  }
  /* Father, cleans up */
  pthread_mutexattr_destroy(&mattr);
  ...
  return;
...