14

I want to share a variable between more than one independent C executables in Linux. That is, a program will write on an array and set a flag so that no other program can use it, and after this operation it'll unset the flag and then another program will read the array. I tried using the same custom header file (containing the variable) in every program, but it seems different instances of the variables are created when the programs are invoked.

Rifat Rousseau
  • 289
  • 1
  • 4
  • 16
  • 8
    hint: IPC (Interprocess Communication), it's too big a topic to address in an answer here. – Nim May 21 '12 at 11:41
  • 2
    Yes, you might want to take a look [here](http://en.wikipedia.org/wiki/Inter-process_communication). Two independent executables are launched in different processes, so you'll have to implement some sort of communication between them, using [sockets](http://www.cs.cf.ac.uk/Dave/C/node28.html), [pipes](http://www.cs.cf.ac.uk/Dave/C/node23.html), etc... or even files. – Eitan T May 21 '12 at 11:47
  • I see. That means, pipe must be used in this case. Is there any simpler way? – Rifat Rousseau May 21 '12 at 11:48
  • @Rifat Pipes are simple enough. [Here's](http://beej.us/guide/bgipc/output/html/multipage/pipes.html) a good explanation to get you introduced to pipes. – Eitan T May 21 '12 at 11:50
  • pipes are indeed simpler than [shared memory](http://en.wikipedia.org/wiki/Shared_memory), I think. You need to serialize your variable, though. – moooeeeep May 21 '12 at 11:57
  • no need to serialize, same machine (same arch)... – Karoly Horvath May 21 '12 at 12:01

2 Answers2

17

Variables you declare in your headers will generate a copy where ever you include them (unless you declare them extern). Of course, when dealing with separate processes every process will have its own memory space. You need to use more sophisticated techniques to circumvent this, i.e. Inter Process Communication (IPC). For example:

  • (named) Pipes
  • Sockets
  • Shared Memory

Your question reads like shared memory is what you want, since hereby multiple processes can access the same memory regions to share some variables. Maybe take a look at this question and its answers for an example.

Your program would be required to create some shared memory, e.g. using shmget and to attach the shared memory object using shmat. When multiple processes access same memory regions, it's always a healthy approach to add process synchronization during read/write on the variable, e.g. using a shared semaphore (semget, semop).

When you are done with your shared memory you need to detach (shmdt) from it. Thereby you tell the kernel that your process no longer needs access to it. The process that created the shared memory/semaphore object also needs to destroy them at the end of your program(s). Otherwise it will reside in memory, probably until you reboot your machine (see shmctl, semctl, especially IPC_RMID).

Note that for shared memory objects "The segment will only actually be destroyed after the last process detaches it". So you want to make sure, that this actually happens for all of your processes (shmdt).


In response to the comments, here is the POSIX approach:

System V shared memory (shmget(2), shmop(2), etc.) is an older shared memory API. POSIX shared memory provides a simpler, and better designed interface; on the other hand POSIX shared memory is somewhat less widely available (especially on older systems) than System V shared memory.

See also this overview and here for examples.

Finally, note that

POSIX shared memory objects have kernel persistence: a shared memory object will exist until the system is shut down, or until all processes have unmapped the object and it has been deleted with shm_unlink(3)


In order to take into account the persistence of the shared memory objects, don't forget to add signal handlers to your application that will perform the clean up operations in case of an exceptional termination (SIGINT, SIGTERM etc.).

moooeeeep
  • 31,622
  • 22
  • 98
  • 187
  • 4
    Don't use `shmget`, use the posix `shm_open` instead. this is much less painful to use, and don't have the problem of key collisions – Hasturkun May 21 '12 at 12:35
  • @Hasturkun - Thanks for the comment! I haven't used these so far, but I added a note on this for completeness. – moooeeeep May 21 '12 at 12:54
  • @Hasturkun Why `shmget` has the problem of key collison? Could you please explain that in more detail for me、 – John Jan 24 '22 at 08:32
  • 1
    @John here you can find some discussion on that topic: https://stackoverflow.com/q/4175379/1025391 – moooeeeep Jan 25 '22 at 08:08
7

Look into using POSIX shared memory via shm_open and shm_unlink... I personally feel they are easier to use and more straight-forward than the older System-V IPC calls such as shmget, etc. since the handle returned works exactly like a file-descriptor that you can use with calls like read, write, etc. Otherwise, if you want access the shared memory object represented by the file-descriptor via normal pointers, you can use mmap on the file-descriptor returned by shm_open.

Jason
  • 31,834
  • 7
  • 59
  • 78