Skip to content

Instantly share code, notes, and snippets.

@junfenglx
Created November 11, 2013 13:12
Show Gist options
  • 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*/
@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