I want to fork multiple processes and then use a semaphore on them. Here is what I tried:
sem_init(&sem, 1, 1); /* semaphore*, pshared, value */
.
.
.
Linux minimal anonymous sem_init + mmap MAP_ANONYMOUS example
I like this setup as it does not pollute any global namespace as sem_open does.
The only downside is that MAP_ANONYMOUS is not POSIX, and I don't know any replacement: Anonymous shared memory? shm_open for example takes a global identifier just like sem_open.
main.c:
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char **argv) {
pid_t pid;
typedef struct {
sem_t sem;
int i;
} Semint;
Semint *semint;
size_t size = sizeof(Semint);
semint = (Semint *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0);
assert(semint != MAP_FAILED);
/* 1: shared across processes
* 0: initial value, wait locked until one post happens (making it > 0)
*/
sem_init(&semint->sem, 1, 0);
semint->i = 0;
pid = fork();
assert(pid != -1);
if (pid == 0) {
sleep(1);
semint->i = 1;
msync(&semint->sem, size, MS_SYNC);
sem_post(&semint->sem);
exit(EXIT_SUCCESS);
}
if (argc == 1) {
sem_wait(&semint->sem);
}
/* Was modified on the other process. */
assert(semint->i == 1);
wait(NULL);
sem_destroy(&semint->sem);
assert(munmap(semint, size) != -1);
return EXIT_SUCCESS;
}
Compile:
gcc -g -std=c99 -Wall -Wextra -o main main.c -lpthread
Run with sem_wait:
./main
Run without sem_wait:
./main 1
Without this synchronization, the assert is very likely to fail, since the child sleeps for one whole second:
main: main.c:39: main: Assertion `semint->i == 1' failed.
Tested on Ubuntu 18.04. GitHub upstream.