I'm trying to learn the IPC UNIX APIs, specifically shared memory. I have created this small program that tries to either access the shared memory segment or create one.
This is what I do:
gcc -Wall -Wextra *.c
# in one terminal
./a.out
# in another
/a.out
The shared.mem
file you can see in the source IS present in the same directory from which I launch the executable.
However, it seems like I'm never actually accessing a previously created shared memory segment (error is "No such file or directory"). I always create a new one - as seen via the ipcs
command line, even though the IPC key stays the same.
What am I doing wrong ?
Below is the code I used, for reference. It compiles at least on Linux.
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define exit_error(what) exit_error_func(what, __FILE__, __LINE__)
#define SHM_SIZE (64)
#define UNUSED(x) (void)(x)
void *shm_addr = NULL;
void exit_error_func(const char *what, const char *file, int line)
{
fprintf(stderr, "Error in %s at line %d: %s. Reason: %s.\n", file, line, what, strerror(errno));
exit(1);
}
void sigint_handler(int sig)
{
shmdt(shm_addr);
UNUSED(sig);
}
int main(void)
{
key_t ipc_key;
int shm_id;
if ((ipc_key = ftok("shared.mem", 1)) == -1)
exit_error("could not get IPC key");
printf("IPC key is %d\n", ipc_key);
if ((shm_id = shmget(ipc_key, SHM_SIZE, 0600)) == -1)
{
printf("could not get SHM id, trying to create one now\n");
if ((shm_id = shmget(ipc_key, SHM_SIZE, IPC_EXCL | IPC_CREAT | 0600)) == -1)
exit_error("could not create or get shared memory segment");
else
printf("created SHM id\n");
}
else
printf("got already existing SHM id\n");
printf("SHM id is %d\n", shm_id);
if ((shm_addr = shmat(shm_id, NULL, 0)) == (void *)-1)
exit_error("could not attach to segment");
signal(SIGINT, sigint_handler);
if (shmctl(shm_id, IPC_RMID, NULL) == -1)
exit_error("could not flag shared memory for deletion");
printf("SHM flagged for deletion\n");
while (1)
sleep(1);
return (0);
}