2

I have two programs in C that need to communicate with each other. There is a single variable that I am storing in shared memory using shmget(key, 27, IPC_CREAT | 0666) in one program. I update this variable every 1 second. From the other program, I access it every 1 second using shmget(key, 27, 0666).

This works great, but after a while (usually a few hours), the program that retrieves the data crashes with a segfault. I used gdb to pinpoint the seg fault to the shmget(key, 27, 0666) line. The error code returned is:

ENOMEM Could not allocate memory for the descriptor or for the page tables.

When I check the shared memory segments from the command prompt using ipcs -m, I currently see this:

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x00000000 65536      root       600        393216     2          dest         
0x00000000 98305      root       600        393216     2          dest         
0x00000000 131074     root       600        393216     2          dest         
0x00000000 163843     root       600        393216     2          dest         
0x00000000 196612     root       600        393216     2          dest         
0x00000000 229381     root       600        393216     2          dest         
0x00000000 262150     root       600        393216     2          dest         
0x00000000 294919     root       600        393216     2          dest         
0x00000000 327688     root       600        393216     2          dest         
0x00000000 589833     root       600        393216     2          dest         
0x00000000 655370     root       600        393216     2          dest         
0x00000000 524299     root       600        393216     2          dest         
0x00000000 688140     root       666        27         0                       
0x0008aa53 720909     root       666        27         31950                   
0x0006f855 753678     root       666        27         33564                   

It seems to me like there's an issue with the shared memory I'm using hitting some kind of maximum? But I'm not sure what to do about that, and I'm finding precious little info by google searching. Any thoughts? This program needs to run for ~24 hours at a time at least, if not longer.

Thank you in advance.

1 Answer 1

5

You seem to misunderstand how to use Sys V shared memory segments. You should not need to perform a shmget() more than once in the same process for the same shared memory segment. You are meant to get a segment ID via shmget(), attach it to your memory space via shmat(), and thereafter simply read and/or write it as many times as you want. Modifications will be visible to other processes that have attached the same shared memory segment.

If you nevertheless do attach the memory segment multiple times, then you must be sure to also detach it each time via shmdt(), else, yes, you will eventually fill up the process's whole address space.

In addition, to use shared memory properly, you need some kind of synchronization mechanism. For this purpose, the natural complement to Sys V shared memory segments is Sys V semaphores. You use this to prevent one process from reading while another process is writing the same data.

Sign up to request clarification or add additional context in comments.

7 Comments

I see what you mean. I changed my shmget() and shmat() to happen only once at the beginning of each program's main function, attaching the memory segment to a global variable for the child function to access (for other reasons I cannot pass it to the child function so must use a global).
I've been running the code with the changes above for almost 24 hours now and it hasn't segfaulted, which is great, but I haven't implemented semaphores yet (I've been reading up on them). Since I am never trying to WRITE to the same shared memory segment from two different programs (one program only reads the segment, the other program writes and reads), is it truly necessary? It seems like a lot to add to a fairly short program if there's no trouble with reading & writing at the same time.
If the variable you are sharing is not of a size and type that will be written to memory atomically, then you have to be concerned about readers seeing it in an inconsistent state. You also have to be concerned with when it actually is written to memory, and when it is actually read, because your friendly compiler may emit machine code that holds that variable's value in a CPU register for a while instead of immediately committing it to memory. A suitable synchronization mechanism solves those problems.
I'm not sure what kind of variables would not be written to memory atomically. There are two variables actually: one is an array of integers of uint_32t type, and the other is a char array of uint8_t size. Thank you very much for your responses.
They are very small arrays also. The uint8_t array just contains 2 integers that are either 1 or 2. I.e.: 1,1 or 1,2 or 2,1 or 2,2. the uint32_t array just contains 2 unsigned integers that can vary.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.