Quaker
Quaker

Reputation: 1553

Sharing a struct with a pointer between two processes using `shm_open()`

I have the following struct,

typedef struct arrays {
    int *array;
    int max;
    int min;
} array;

Where *array points to an dynamically allocated array, max and min holds the maximum and minimum numbers in the array.

I need to share an instance (can I use the word 'instance' in C?) of this struct between two processes, am I supposed to use shm_open() first for allocating the array pointed by *array and second for allocating the struct itself, or is there a better way achieving the same result?

Upvotes: 0

Views: 3218

Answers (3)

n. m. could be an AI
n. m. could be an AI

Reputation: 119877

You need to do this.

  1. Use shm_open in each process to get a file descriptor. You must pass shm_open the same name in each process. The name is what distinguishes the shared memory region from other shared memory regions. The name must begin with a slash: "/somename".
  2. Use the file descriptor obtained in step 1 to call mmap.
  3. The address returned from mmap is your shared memory address. It is random and different in each process.
  4. Because of 3, you cannot use pointers inside a shared memory region. You need to either use integer offsets from the start of the shared memory, or do away with indirection altogether. For instance, treat the entire shared memory region as an integer array. The first two cells hold min and max and the actual numbers start after that.
  5. mmap will return usable memory, you don't need to allocate any buffers either statically or with malloc.

Upvotes: 2

Charlie Martin
Charlie Martin

Reputation: 112366

Okay, the first asnwer is like when you tell the doctor "It hurts when I do this" and the doctor says "then dont DO that!"

Assuming you're intent on this, remember that shm_open makes a block of memory avaiailable for sharing: if you have a pointer to malloc'd memory in the memory you share, it will be a pointer to some random address in the heap as far as the other process is concerned. You need to allocate the whole buffer, the whole chunk of memory, and then share that.

Update

Per the question below, if you want to allocate the buffer during runtime then the canonical way would be:

#define HOWBIGISMYBUFFER (3*GAZILLION)
char * buf;
if((buf = malloc(HOWBIGISMYBUFFER)) == 0){
    /* make splodey noises and terminate */
}
/* now you have your buffer */

where, of course GAZILLION is defined elsewhere. That said, however, you don't want to do that. What you're trying to achieve is a static block of memory that can be shared, and allocating it on the heap exposes you to all sorts of very hard to track bugs. (Consider, eg, you allocate the memory in program A, share it to program B, and program B then corrupts program A's heap by a buffer overflow. Or consider, what if program B keeps running after program A crashes?)

What you want to do instead is create a static buffer. The easiest way is by making a .h file:

/* my_buffer.h */
char bfr[HOWBIGISMYBUFFER];

and then including that anywhere you want to share the memory. What I would do instead is write a module:

/* my_buffer.c */
char bfr[HOWBIGISMYBUFFER];

char * init(){ /* do your shm_open here and returna pointer to bfr */ } 

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409196

I don't know if it's better but you can do it with only a single allocation: Allocate one large buffer to include both the structure and the array, then make array point to the buffer + the size of the structure.

Upvotes: 3

Related Questions