system V semaphore

A semaphore is a very important inter process communication used to provide synchronization between multiple process and threads of a process.

Unlike other IPC’s it does not provide any communication between processes. Rather acts as a synchronization mechanism among process.

Analogy of semaphore: let’s consider two train travelling in same direction and heading towards the railway station with single platform. As only one train can occupy the platform, one of the train is signaled to stop before the station and occupy the platform once the first train has left the station.

This can be understood with  two process accessing a single memory location.

sem1

Semaphore solves two important problem in RTOS environment: locking of critical section and race condition.

Critical section: A shared piece of code, which need to be executed uninterruptedly is called a critical section, concurrent access of this piece of code may lead to undefined behavior. A critical section will usually terminate in fixed time.

Semaphore helps to solve the problem by synchronizing the process to access the critical section.

Race condition: A race condition is an undesirable situation, when two or more process/thread is trying to perform operation on same resource (memory or device) at same time. This can be a serious issue were sequence of order is mandatory.

Let’s work with example: a race condition may occur if two process are working on same memory. Process A to read and process B to write.

If process A is slow with respect to process B, in this case the process B may overwrite the older content before the content is read by process A. This can lead to unexpected behavior.

This race condition problem can be solved by semaphore via synchronization of process A and process B.

System V API:

INITIALIZING A SEMAPHORE SET:

SYSTEM CALL: semget();

PROTOTYPE: int semget (key_t key, int nsems, int semflg);

RETURNS: semaphore set IPC identifier on success and -1 on error

Key: unique identification number for the semaphore.

Nsems: no of semaphore

Semflg: access permission for semaphore created.

SEMAPHORE OPERATIONS:

      SYSTEM CALL: semop();

PROTOTYPE: int semop ( int sem_num, struct sembuf * sem_op, unsigned sem_flg);

RETURNS: 0 on success (all operations performed) and -1 on error

sem_num:The number of the semaphore you wish to deal with

sem_op : The operation to perform (positive, negative, or zero)

sem_flg: Operational flags

This structure is declared in linux/sem.h as follows:

struct sembuf

{

ushort  sem_num;        /* semaphore index in array */

short   sem_op;          /* semaphore operation */

short   sem_flg;        /* operation flags */

};

CONTROLLING SEMAPHORES:

SYSTEM CALL: semctl();

PROTOTYPE: int semctl ( int semid, int semnum, int cmd, union semun arg );

RETURNS: positive integer on success  or -1 on error

The cmd argument represents the command to be performed as given below.

IPC_STAT

Retrieves the semid_ds structure for a set, and stores it in the address of the buf argument in the semun union.

IPC_SET

Sets the value of the ipc_perm member of the semid_ds structure for a set. Takes the values from the buf argument of the semun union.

IPC_RMID

Removes the set from the kernel.

GETALL

Used to obtain the values of all semaphores in a set. The integer values are stored in an array of unsigned short integers pointed to by the array member of the union.

GETNCNT

Returns the number of processes currently waiting for resources.

GETPID

Returns the PID of the process which performed the last semop call.

GETVAL

Returns the value of a single semaphore within the set.

GETZCNT

Returns the number of processes currently waiting for 100% resource utilization.

SETALL

Sets all semaphore values with a set to the matching values contained in the array member of the union.

SETVAL

Sets the value of an individual semaphore within the set to the val member of the union.

The arg argument represents an instance of type semun. This particular union is declared in linux/sem.h as follows:

/* arg for semctl system calls. */

union semun

{

int val;                /* value for SETVAL */

struct semid_ds *buf;   /* buffer for IPC_STAT & IPC_SET */

ushort *array;          /* array for GETALL & SETALL */

struct seminfo *__buf;  /* buffer for IPC_INFO */

void *__pad;

};

Val:Used when the SETVAL command is performed. Specifies the value to set the semaphore to.

Buf:Used in the IPC_STAT/IPC_SET commands. Represents a copy of the internal semaphore data structure used in the kernel.

Array:A pointer used in the GETALL/SETALL commands. Should point to an array of integer values to be used in setting or retrieving all semaphore values in a set.

 

Kernel configuration of semaphore:

CMD: ipcs  -ls

 semaphore

For more information related kernel configuration of semaphore check my article in below link.

https://blogcwi.wordpress.com/2015/04/10/kernel-config_final-docx/

 

program 1:

Let’s write a basic code to create semaphore using semget() system call.

 sem_create

Explanation:

Line 4       : header files, semaphore.

Line 9-10: Variable declaration for semaphore ID and Key no.

Line 14-18: Semaphore is created with key no, three semaphore and access permission of

IPC_CREAT|0666. Print the semaphore ID.

IPC_CREAT:Create the segment if it doesn’t already exist in the kernel.

0666: all users (owner, group and others) can read and write but cannot execute.

Line 20-24: Semaphore is created with key no, three semaphore and access permission of

IPC_CREAT|IPC_EXCL|0666. Print the semaphore ID.

IPC_CREAT:Create the segment if it doesn’t already exist in the kernel.

IPC_EXCL: When used with IPC_CREAT, fail if semaphore set already exists.

0666:  all users (owner, group and others) can read and write but cannot execute.

Line 26-30: Semaphore is created with IPC_PRIVATE, three semaphore and access permission of 0666.

Print the semaphore ID.

IPC_PRIVATE: A new set of semaphores is created if key has the value IPC_PRIVATE.

0666:  all users (owner, group and others) can read and write but cannot execute.

Result:

create_sem_res

Explanation :

Semaphore Id is printed for first as 0,  second semaphore show existence of same semaphore ID in kernel. final semaphore is created with ID :32769

 Program 2:

fork - 1

fork

Below is a program were parent and child process is synchronized to share the terminal to print.

Explanation:

Line 1-7     : header files.

Line 8        : No of semaphore defined as constant using a preprocessor directives.

Line 20-23:  variable for semaphore ID, Key and process ID.

Line 23-24: data string to be printed in child and data1 string to be printed in parent.

Line 25       :   object for union senum used to store set initial value. Whether take or released.

Line 26-27: structure is defined and initialized to take the semaphore by using object P and release the semaphore using object V.

Line 36-40: Random no is generated using a ftok function and stored in key, to be used in semget system call.

Line 42-46: Semaphore ID is generated using semget system call, with a key no, only one semaphore is created and with IPC_CTEAT|0666 access permission.

Line 50: parent and child process is created using a fork(), child process returns zero and parent process return child process ID. Switch condition is executed on return value of parent and child process.

Line 53-58:Child is executed,  arg the object of union semun, arg.val is set to Release state and using semctl system call arg.val is initialized. Only once.

Line 63-81: loop of 10 is executed one of the other alternatively with parent process. each time child process locks the terminal and displays the content and release the terminal using semaphore via semop system call.

Line 86-108: Parent is executed, loop of 10 is executed one of the other alternatively with child process. each time parent process locks the terminal and displays the content and release the terminal using semaphore via semop system call.

Line 113: returns the process ID of the calling process.

Line 118-123: the semaphore created is removed from kernel using semctl system call.

Result:

res

Explaination:

The content from parent and child is being printed alternatively, which is being synchronized by semaphore.

Program 3:

Two process is made to synchronize, so that they can print one after the other on the same terminal.

Sem1.c

sem1 - Copy

sem1

Explaination:

Line 1-9: header files.

Line 13: preprocessor directive is used for defining constant for semaphore key to be used at semget system call.

Line 15: function1 declaration.

Line 17: sem_set_ID is used to store semaphore ID from semget.

Line 18-28: void sem_lock is a function to be called to lock a resource.

Line 30-40:void sem_unlock is a function to be called to unlock a resource.

Line 45-49: union semun is declared.

Line 51: variable is declared to store value of semctl system call.

Line 55-59: semget system call is used to create a semaphore.

Line 69 : function1() is called.

Line 71: process ID of the process is printed.

Line73-82: semaphore is removed from kernel.

Line 87-102: function1(), loop runs for 10 time by locking ,printing on screen and unlocking the resource.  this alternatively printed with the other program(sem2.c).

Sem2.c

sem2 - Copy

sem2

Explanation:

Line 1-11: header files.

Line 12: preprocessor directive is used for defining constant for semaphore key to be used at semget system call.

Line 14: function1 declaration.

Line 16: sem_set_ID is used to store semaphore ID from semget.

Line 17-27: void sem_lock is a function to be called to lock a resource.

Line 28-39:void sem_unlock is a function to be called to unlock a resource.

Line 44-48: union semun is declared.

Line 53-57: semget system call is used to create a semaphore.

Line 59: function2() is called.

Line 61: process ID is printed.

Line 68-84: function2(),loop runs for 10 time by locking ,printing on screen and unlocking the resource.  this alternatively printed with the other program(sem1.c).

Result:

res

Explanation:

It can be seen from the Result that Sem1.c and sem2.c content are being printed alternatively, which is being synchronized


Leave a comment