Skip to content

Instantly share code, notes, and snippets.

@ben-cohen
Created July 12, 2017 19:25
Show Gist options
  • Save ben-cohen/67d41a917ffbf7a5da99fd622feb346b to your computer and use it in GitHub Desktop.
Save ben-cohen/67d41a917ffbf7a5da99fd622feb346b to your computer and use it in GitHub Desktop.
Mutex in mmap memory shared between processes.
/*
* shared_mutex: Mutex in mmap memory shared between processes.
*
* Ben Cohen, July 2017.
*
* Compile using:
* gcc -o shared_mutex shared_mutex.c -ggdb -Wall -std=c99 -pthread
*
* Two processes are created with an mmap shared memory region
* containing an array of chars and a mutex. The mutex is created with
* the attribute PTHREAD_PROCESS_SHARED.
*
* One process writes increasing numbers into an array and the other
* prints the contents once a second.
*
* By default the mutex will prevent the first process updating while
* the second is reading so all the value in each row will be the same,
* for example:
*
* 0 0 0 0 0 0 0 0 0 0
* 79 79 79 79 79 79 79 79 79 79
* 209 209 209 209 209 209 209 209 209 209
* 122 122 122 122 122 122 122 122 122 122
* 106 106 106 106 106 106 106 106 106 106
* ...
*
* If invoked with the argument --no-mutex then it does not obtain the
* mutex so the values are modified while the second process reads the
* array and the values in each row will not all be the same:
*
* 130 206 230 236 241 247 253 3 12 20
* 16 22 28 34 39 45 51 57 63 69
* 196 186 193 200 206 211 217 223 228 234
* 133 104 112 118 123 128 133 138 144 150
* 136 111 116 122 128 133 138 143 149 154
* ...
*/
#define _BSD_SOURCE
#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#define MMAP_NAME "/tmp/mmaptest"
#define LENGTH sizeof(struct mapped)
#define ARRAY_ELEMENTS 10
struct mapped
{
unsigned char array[ARRAY_ELEMENTS];
int use_mutex;
pthread_mutex_t mutex;
};
void die(char *msg)
{
perror(msg);
exit(1);
}
void child(struct mapped *mapping)
{
unsigned int n = 0;
while (1)
{
if (mapping->use_mutex)
pthread_mutex_lock(&mapping->mutex);
for (int i = 0; i < 10; i ++)
{
mapping->array[i] = n;
}
n ++;
if (mapping->use_mutex)
pthread_mutex_unlock(&mapping->mutex);
}
}
void parent(struct mapped *mapping)
{
while (1)
{
if (mapping->use_mutex)
pthread_mutex_lock(&mapping->mutex);
for (int i = 0; i < 10; i ++)
{
printf("%4d", mapping->array[i]);
}
printf("\n");
if (mapping->use_mutex)
pthread_mutex_unlock(&mapping->mutex);
sleep(1);
}
}
int main(int argc, char **argv)
{
int rc;
unlink(MMAP_NAME);
int fd = open(MMAP_NAME, O_CREAT|O_RDWR, 00600);
if (fd == -1)
die("open");
rc = ftruncate(fd, LENGTH);
if (rc != 0)
die("ftruncate");
struct mapped *mapping = (struct mapped *)mmap(NULL,
LENGTH,
PROT_READ|PROT_WRITE,
MAP_SHARED,
fd,
0);
if (mapping == MAP_FAILED)
die("mmap");
close(fd);
pthread_mutexattr_t mutexattr;
rc = pthread_mutexattr_init(&mutexattr);
if (rc != 0)
die("pthread_mutexattr_init");
rc = pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
if (rc != 0)
die("pthread_mutexattr_setpshared");
pthread_mutex_init(&mapping->mutex, &mutexattr);
if (rc != 0)
die("pthread_mutex_init");
if (argc >= 2
&& strcmp(argv[1], "--no-mutex") == 0)
mapping->use_mutex = 0;
else
mapping->use_mutex = 1;
switch (fork())
{
case -1:
die("fork");
case 0:
child(mapping);
break;
default:
parent(mapping);
break;
}
rc = munmap(mapping, LENGTH);
if (rc != 0)
die("munmap");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment