Semaphores allow processes to avoid clashes when accessing shared resources, for instance shared memory.
Generating A Random Key
Humans aren't very good at picking random values so use a site like this one: www.random.org/integers/
It won't do a 32bit 1 to 2147483647, but it will do 1 to 1000000000
Simple Example Of Creating & Using A Semaphore
Header Files Needed
#include <sys/sem.h> //Used for semaphores
Defining The Semaphore Your Header File
//----- SEMAPHORE -----
//On linux systems this union is probably already defined in the included sys/sem.h, but if not use this default basic definition:
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
};
//FUNCTIONS:
static int semaphore1_get_access(void);
static int semaphore1_release_access(void);
//VARIABLES:
static int semaphore1_id;
The Functions
//***********************************************************
//***********************************************************
//********** WAIT IF NECESSARY THEN LOCK SEMAPHORE **********
//***********************************************************
//***********************************************************
//Wait if necessary and then change the semaphore by –1. This is the "wait" operation
static int semaphore1_get_access(void)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1; /* P() */
sem_b.sem_flg = SEM_UNDO;
if (semop(semaphore1_id, &sem_b, 1) == -1) //Wait until free
{
fprintf(stderr, "semaphore1_get_access failed\n");
return(0);
}
return(1);
}
//***************************************
//***************************************
//********** RELEASE SEMAPHORE **********
//***************************************
//***************************************
//Setting the semaphore back to available. This is the "release" operation.
static int semaphore1_release_access(void)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1; /* V() */
sem_b.sem_flg = SEM_UNDO;
if (semop(semaphore1_id, &sem_b, 1) == -1)
{
fprintf(stderr, "semaphore1_release_access failed\n");
return(0);
}
return(1);
}
Create The Semaphore
//----------------------------
//----- CREATE SEMAPHORE -----
//----------------------------
printf("Creating semaphore...\n");
semaphore1_id = semget((key_t)12345, 1, 0666 | IPC_CREAT); //<<<<< SET THE SEMPAHORE KEY (Semaphore key, number of semaphores required, flags)
// Semaphore key
// Unique non zero integer (usually 32 bit). Needs to avoid clashing with another other processes semaphores (you just have to pick a random value and hope - ftok() can help with this but it still doesn't guarantee to avoid colision)
//Initialize the semaphore using the SETVAL command in a semctl call (required before it can be used)
union semun sem_union_init;
sem_union_init.val = 1;
if (semctl(semaphore1_id, 0, SETVAL, sem_union_init) == -1)
{
fprintf(stderr, "Creating semaphore failed to initialize\n");
exit(EXIT_FAILURE);
}
Using The Semaphore
//----- SEMAPHORE GET ACCESS -----
if (!semaphore1_get_access())
exit(EXIT_FAILURE);
//... do the interlocked action ...
//----- SEMAPHORE RELEASE ACCESS -----
if (!semaphore1_release_access())
exit(EXIT_FAILURE);
Deleting The Semaphore
//----------------------------
//----- DELETE SEMAPHORE -----
//----------------------------
//It's important not to unintentionally leave semaphores existing after program execution. It also may cause problems next time you run the program.
union semun sem_union_delete;
if (semctl(semaphore1_id, 0, IPC_RMID, sem_union_delete) == -1)
fprintf(stderr, "Failed to delete semaphore\n");
