Created
November 11, 2013 13:12
-
-
Save junfenglx/7412986 to your computer and use it in GitHub Desktop.
named semaphores use example.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> /* printf() */ | |
#include <stdlib.h> /* exit(), malloc(), free() */ | |
#include <unistd.h> | |
#include <sys/types.h> /* key_t, sem_t, pid_t */ | |
#include <sys/wait.h> | |
#include <sys/shm.h> /* shmat(), IPC_RMID */ | |
#include <errno.h> /* errno, ECHILD */ | |
#include <semaphore.h> /* sem_open(), sem_destroy(), sem_wait().. */ | |
#include <fcntl.h> /* O_CREAT, O_EXEC */ | |
int main (int argc, char **argv){ | |
int i; /* loop variables */ | |
key_t shmkey; /* shared memory key */ | |
int shmid; /* shared memory id */ | |
sem_t *sem; /* synch semaphore *//*shared */ | |
pid_t pid; /* fork pid */ | |
int *p; /* shared variable *//*shared */ | |
unsigned int n; /* fork count */ | |
unsigned int value; /* semaphore value */ | |
/* initialize a shared variable in shared memory */ | |
shmkey = ftok ("/dev/null", 5); /* valid directory name and a number */ | |
printf ("shmkey for p = %d\n", shmkey); | |
shmid = shmget (shmkey, sizeof (int), 0644 | IPC_CREAT); | |
if (shmid < 0){ /* shared memory error check */ | |
perror ("shmget\n"); | |
exit (1); | |
} | |
p = (int *) shmat (shmid, NULL, 0); /* attach p to shared memory */ | |
*p = 0; | |
printf ("p=%d is allocated in shared memory.\n\n", *p); | |
/********************************************************/ | |
printf ("How many children do you want to fork?\n"); | |
printf ("Fork count: "); | |
scanf ("%u", &n); | |
printf ("What do you want the semaphore value to be?\n"); | |
printf ("Semaphore value: "); | |
scanf ("%u", &value); | |
/* initialize semaphores for shared processes */ | |
sem = sem_open ("pSem", O_CREAT | O_EXCL, 0644, value); | |
/* name of semaphore is "pSem", semaphore is reached using this name */ | |
sem_unlink ("pSem"); | |
/* unlink prevents the semaphore existing forever */ | |
/* if a crash occurs during the execution */ | |
printf ("semaphores initialized.\n\n"); | |
/* fork child processes */ | |
for (i = 0; i < n; i++){ | |
pid = fork (); | |
if (pid < 0) /* check for error */ | |
printf ("Fork error.\n"); | |
else if (pid == 0) | |
break; /* child processes */ | |
} | |
/******************************************************/ | |
/****************** PARENT PROCESS ****************/ | |
/******************************************************/ | |
if (pid != 0){ | |
/* wait for all children to exit */ | |
while (pid = waitpid (-1, NULL, 0)){ | |
if (errno == ECHILD) | |
break; | |
} | |
printf ("\nParent: All children have exited.\n"); | |
/* shared memory detach */ | |
shmdt (p); | |
shmctl (shmid, IPC_RMID, 0); | |
/* cleanup semaphores */ | |
printf("sem_destroy return value:%d\n",sem_destroy (sem)); | |
exit (0); | |
} | |
/******************************************************/ | |
/****************** CHILD PROCESS *****************/ | |
/******************************************************/ | |
else{ | |
sem_wait (sem); /* P operation */ | |
printf (" Child(%d) is in critical section.\n", i); | |
sleep (1); | |
*p += i % 3; /* increment *p by 0, 1 or 2 based on i */ | |
printf (" Child(%d) new value of *p=%d.\n", i, *p); | |
sem_post (sem); /* V operation */ | |
exit (0); | |
} | |
} | |
/*src:http://stackoverflow.com/a/16400833*/ |
in line 81 there might be an undefined behavior since "Only a semaphore that was created using sem_init(3RT) may be destroyed using sem_destroy(); the effect of calling sem_destroy() with a named semaphore is undefined".
from POSIX: http://pubs.opengroup.org/sem_destroy
I believe that the call of sem_destory at line 81 should be replaced by the call of comabination of sem_close and sem_unlink. Only by this way the file created by the sem_open at the /dev/shm/* could be properly removed.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
in line 46, shouldn't a name for a named semaphore start with a '/' character as stated in the sem_overview(7) man?
Named semaphores
A named semaphore is identified by a name of the form /somename; that is, a null-terminated string of up to NAME_MAX-4 (i.e., 251) characters consisting of an initial slash, followed by one or more characters, none of which are slashes. Two processes can operate on the same named semaphore by passing the same name to sem_open(3).
taken from https://linux.die.net/man/7/sem_overview