Skip to content

Instantly share code, notes, and snippets.

@junfenglx
Created November 11, 2013 13:12
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save junfenglx/7412986 to your computer and use it in GitHub Desktop.
Save junfenglx/7412986 to your computer and use it in GitHub Desktop.
named semaphores use example.
#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*/
@abondarev84
Copy link

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

@sogreshilin
Copy link

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

@leemeans
Copy link

leemeans commented Feb 27, 2019

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