Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C - fork() and sharing memory

I need my parent and child process to both be able to read and write the same variable (of type int) so it is "global" between the two processes.

I'm assuming this would use some sort of cross-process communication and have one variable on one process being updated.

I did a quick google and IPC and various techniques come up but I don't know which is the most suitable for my situation.

So what technique is best and could you provide a link to a noobs tutorial for it.

Thanks.

like image 486
Cheetah Avatar asked Apr 21 '10 11:04

Cheetah


3 Answers

Since you are mentioning using fork(), I assume that you are living on a *nix-System

From Unix.com

The primary way to share data between processes using UNIX IPCs are:

(1) Shared memory;

(2) Sockets:

There are other UNIX IPCs including

(3) Message Queues.

(4) Semaphores;

(5) Signals.

Your best bet (for IPCs) is to use shared memory segments, based on your post. You might need to use semaphores to insure that the shared memory operations are atomic.

A tutorial on forking and shared memory is on dev shed:

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

another more in-depth description of using multithreading (if appilcable for your application) can be found here:

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

like image 110
sum1stolemyname Avatar answered Nov 13 '22 21:11

sum1stolemyname


If you need to share memory, perhaps using threads instead of processes would be a better solution?

like image 38
michalburger1 Avatar answered Nov 13 '22 21:11

michalburger1


A variant that I used recently of shared memory is to open a mmap before forking. This avoids certain restrictions of the shared memory api. You don't have a size limit (the address range is limit), you don't need to generate the key from that absolute file. Here an example how I did it (I left out the error checking for the sake of brevity)

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;
like image 32
Patrick Schlüter Avatar answered Nov 13 '22 20:11

Patrick Schlüter