I have the following program to exercise using forks and shared memory.
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <sys/ipc.h>
int main() {
int bignum = 1000000;
key_t key = ftok(".", 'x');
int shmid = shmget(key, sizeof(int)*bignum, IPC_CREAT | 0666);
if (shmid < 0) {
perror("shmget\n");
return 1;
}
int *arr = shmat(shmid, NULL, 0);
pid_t c1 = fork();
if (c1==0) {
pid_t c2 = fork();
if (c2==0) {
pid_t c3 = fork();
if (c3==0) {
arr[0] = 10;
} else {
arr[1] = 11;
}
wait(NULL);
exit(0);
} else {
arr[2] = 12;
}
wait(NULL);
exit(0);
} else {
arr[3] = 13;
wait(NULL);
for (int i=0; i<4; i++) printf("%d ", arr[i]);
printf("\n");
}
shmdt(arr);
shmctl(shmid, IPC_RMID, NULL);
exit(0);
}
I previously ran this program using a smaller amount of shared memory and have now increased it to see if that affects the program in any way. When I run this I get:
shmget
: Invalid argument
I’ve seen this post: C linux shmget Invalid argument
I’ve tried following the advice, but I’m unfamiliar with ipcs and ipcrm. I ran ipcs in a terminal and it gave me some shared memory info. But I can’t tell which is the one allocated by the program, there’s a lot, and I can’t tell what is safe to remove or not.
It also seems odd to me that you wouldn’t just do this inside the C program itself, so that makes me wonder if there isn’t a better way to resolve this issue. I particularly don’t get why the calls to shmdt and shmctl don’t make this a non-issue. Is there some other way to "undo" memory sharing?
Edit: The question was closed because it is similar to this:
C – System V – remove shared memory segment
However, that uses code that is already in my code — so it doesn’t seem to answer the question.
>Solution :
The old program left a smaller shared memory segment lingering after it exited so attaching to it, requesting a bigger size, fails. You can start your new program by removing it:
key_t key = ftok(".", 'x');
int shmid = shmget(key, 1, 0666); // no IPC_CREAT
if (shmid != -1) { // ok, there was a memory segment there already
shmctl(shmid, IPC_RMID, NULL); // remove it
}
// now create the new one
shmid = shmget(key, sizeof(int)*bignum, IPC_CREAT | 0666);