In this chapter we shall learn about:
1. Introduction
2. How to get a System V semaphore?
3. How to control a System V semaphore?
4. How to perform operations a System V semaphore?
5. How to destroy a System V semaphore?
6. Example: SemInit.c
7. Example: SemDemo.c
8. Example: SemRemove.c
Introduction:
In the previous chapter we learned about shared memory. And there is a problem of race condition when there are multiple process are trying to access and change the shared memory.
Now, we have 2 different API to use semaphores. System V semaphore are the older version and POSIX semaphore API which are newer version.
In this chapter we shall learn about System V semaphore.
So to solve this problem we should use semaphores to avoid the race condition.
We shall learn about semaphores by taking series of simple steps and then taking a full example.
1. How to get a System V semaphore?
To get a semaphore you need to use “semget()” system call.
The function prototype is:
#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget(key_t key, int nsems, int semflg);
Here:
key : It is a unique identifier, if any process wants to connect to the queue, it should have to use the same key.
As key is a “long” data type, you can use any integer to set the key.
Or you can also use “ftok()” known as “file to key”. The function accepts 2 arguments, first is file path and the next is a id. “ftok()” will use these 2 arguments and then will create a unique key. The other program trying to access this queue should use the same parameters.
Function prototype for ftok is:
key_t ftok(const char *path, int id);
nsems : It is the number of semaphores in the present semaphore set.
Below is the way to create a semaphore:
#include <sys/ipc.h> #include <sys/sem.h> key_t key; int semid; key = ftok("/home/aj/myFile", 'E'); semid = semget(key, 10, 0666 | IPC_CREAT);
Once a semaphore is created, they’re all uninitialized; to make them free, you need to use semop() or semctl(). We shall see in further in this chapter.
2. How to control a System V semaphore?
To control a semaphore use “semctl()” system call.
“semctl()” will allow to initialize a positive value the semaphores, to make the resources available.
It allows you set for individual semaphore or complete semaphore set.
Function prototype is:
int semctl(int semid, int semnum, int cmd, ... /*arg*/);
union semun { int val; /* used for SETVAL only */ struct semid_ds *buf; /* used for IPC_STAT and IPC_SET */ ushort *array; /* used for GETALL and SETALL */ };
3. How to perform operations a System V semaphore?
To perform operations on a semaphore, you need to use semop() system call.
Syntax for semop():
int semop(int semid, struct sembuf *sops, unsigned int nsops);
Here:
semid: It is the ID you get, when you call semget().
sops: It ss a pointer to the “struct sembuf” which is filled with semaphore commands.
If sem_op is negative, then its value is subtracted from the semaphore.
If sem_op is positive, then it’s value is added to the semaphore.
if sem_op is zero (0), then the calling process will sleep() until the semaphore’s value is 0
4. How to destroy a System V semaphore?
A semaphore can be destroyed by calling semctl() with the cmd IPC_RMID.
Example:
semctl(semid, 0, IPC_RMID);
SemInit.c [Run this first]
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> //for more tutorials on C, C++, STL, DS visit www.ProDeveloperTutorial.com int main(void) { key_t key; int semid; union semun arg; if ((key = ftok("semdemo.c", 'J')) == -1) { perror("ftok"); exit(1); } /* create a semaphore set with 1 semaphore: */ if ((semid = semget(key, 1, 0666 | IPC_CREAT)) == -1) { perror("semget"); exit(1); } /* initialize semaphore #0 to 1: */ arg.val = 1; if (semctl(semid, 0, SETVAL, arg) == -1) { perror("semctl"); exit(1); } return 0; }
SemDemo.c
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> //for more tutorials on C, C++, STL, DS visit www.ProDeveloperTutorial.com int main(void) { key_t key; int semid; struct sembuf sb = {0, -1, 0}; /* set to allocate resource */ if ((key = ftok("semdemo.c", 'J')) == -1) { perror("ftok"); exit(1); } /* grab the semaphore set created by seminit.c: */ if ((semid = semget(key, 1, 0)) == -1) { perror("semget"); exit(1); } printf("Press return to lock: "); getchar(); printf("Trying to lock...\n"); if (semop(semid, &sb, 1) == -1) { perror("semop"); exit(1); } printf("Locked.\n"); printf("Press return to unlock: "); getchar(); sb.sem_op = 1; /* free resource */ if (semop(semid, &sb, 1) == -1) { perror("semop"); exit(1); } printf("Unlocked\n"); return 0; }
SemRemove.c
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> //for more tutorials on C, C++, STL, DS visit www.ProDeveloperTutorial.com int main(void) { key_t key; int semid; union semun arg; if ((key = ftok("semdemo.c", 'J')) == -1) { perror("ftok"); exit(1); } /* grab the semaphore set created by seminit.c: */ if ((semid = semget(key, 1, 0)) == -1) { perror("semget"); exit(1); } /* remove it: */ if (semctl(semid, 0, IPC_RMID, arg) == -1) { perror("semctl"); exit(1); } return 0; }