Skip to content

Instantly share code, notes, and snippets.

@garcia556
Created December 3, 2017 21:08
Show Gist options
  • Star 28 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save garcia556/8231e844a90457c99cc72e5add8388e4 to your computer and use it in GitHub Desktop.
Save garcia556/8231e844a90457c99cc72e5add8388e4 to your computer and use it in GitHub Desktop.
POSIX shared memory IPC example (shm_open, mmap), working on Linux and macOS
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define STORAGE_ID "/SHM_TEST"
#define STORAGE_SIZE 32
int main(int argc, char *argv[])
{
int res;
int fd;
char data[STORAGE_SIZE];
pid_t pid;
void *addr;
pid = getpid();
// get shared memory file descriptor (NOT a file)
fd = shm_open(STORAGE_ID, O_RDONLY, S_IRUSR | S_IWUSR);
if (fd == -1)
{
perror("open");
return 10;
}
// map shared memory to process address space
addr = mmap(NULL, STORAGE_SIZE, PROT_READ, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED)
{
perror("mmap");
return 30;
}
// place data into memory
memcpy(data, addr, STORAGE_SIZE);
printf("PID %d: Read from shared memory: \"%s\"\n", pid, data);
return 0;
}
#!/bin/bash
function is_linux
{
if [[ "$(uname)" == "Linux" ]]; then
echo 1
return
fi
echo 0
}
SET="set"
GET="get"
CFLAGS=""
if [[ "$(is_linux)" == "1" ]]; then
CFLAGS="-lrt"
fi
cc ${CFLAGS} -o ${SET} ${SET}.c
cc ${CFLAGS} -o ${GET} ${GET}.c
./${SET} &
sleep 1
./${GET}
if [[ "$(is_linux)" == "1" ]]; then
echo "/dev/shm:"
ls -l /dev/shm
fi
sleep 1
rm ${SET} ${GET}
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define STORAGE_ID "/SHM_TEST"
#define STORAGE_SIZE 32
#define DATA "Hello, World! From PID %d"
int main(int argc, char *argv[])
{
int res;
int fd;
int len;
pid_t pid;
void *addr;
char data[STORAGE_SIZE];
pid = getpid();
sprintf(data, DATA, pid);
// get shared memory file descriptor (NOT a file)
fd = shm_open(STORAGE_ID, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (fd == -1)
{
perror("open");
return 10;
}
// extend shared memory object as by default it's initialized with size 0
res = ftruncate(fd, STORAGE_SIZE);
if (res == -1)
{
perror("ftruncate");
return 20;
}
// map shared memory to process address space
addr = mmap(NULL, STORAGE_SIZE, PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED)
{
perror("mmap");
return 30;
}
// place data into memory
len = strlen(data) + 1;
memcpy(addr, data, len);
// wait for someone to read it
sleep(2);
// mmap cleanup
res = munmap(addr, STORAGE_SIZE);
if (res == -1)
{
perror("munmap");
return 40;
}
// shm_open cleanup
fd = shm_unlink(STORAGE_ID);
if (fd == -1)
{
perror("unlink");
return 100;
}
return 0;
}
@aigoncharov
Copy link

aigoncharov commented Oct 31, 2020

Thank you! It helped me with my college course!

@jiapengwen
Copy link

what is the different betweent shm_open+mmap and shmget? I suggest is the same

@hbwang15
Copy link

what is the different betweent shm_open+mmap and shmget? I suggest is the same

一个是posix一个是systemv

@MSK61
Copy link

MSK61 commented Jul 29, 2023

I think get.c is missing an munmap call at the end, just like set.c. And both files are missing a close(fd) at the end as well.

@MSK61
Copy link

MSK61 commented Jul 30, 2023

And generally it's best to close the file descriptor right after the memory is mapped with mmap.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment