What Is Semaphore In Linux?

Learn via video courses
Topics Covered

Introduction

Computational and memory resources are limited in a system, and multiple processes need to share these resources to ensure the performant working of a system. As multiple processes compete with each other for these limited resources, we need a method to control the sharing of these resources between multiple processes efficiently. Semaphores are one such technique.

Semaphore in Linux is a technique used for coordinating and synchronizing the activities of multiple processing competing for the same resources.

What are Semaphores?

A Semaphore in Linux is essentially an integer variable that is used to control access to a shared resource in Linux by multiple processes. Semaphores are simple control mechanisms that facilitate inter-process communications (IPC) and allow processes to coordinate their access to shared resources to avoid race conditions and excessive resource utilization.

semaphore-in-linux1

Semaphores were first introduced by Dutch scientist Edsger Dijkstra in 1965 as a simple way to control access to shared resources by processes. This concept was later on added to the Unix kernel and, down the line, the Linux kernel.

A semaphore is usually implemented as an integer with two operations:

  1. Increment (post or signal): The increment operation is used to increase the value of a semaphore.

  2. Decrement (wait or acquire): The decrement operation is used to decrement or reduce the value of a semaphore.

A resource is indicated as 'available' when the value of a semaphore in Linux is positive. On the other hand, a resource is indicated as 'busy' or 'blocked' when the value of a semaphore is negative.

For this reason, increment operations are also called post or signal operations because the signal that a semaphore value has been incremented, and the decrement operations are called wait operations because they denote that a semaphore has been decremented and processes need to wait for the semaphore to be incremented.

Types of Semaphore

In theory, semaphores are of two types: binary semaphores and counting semaphores.

As the name suggests, binary semaphores are semaphores that can only have two values: 0 and 1. These are used to synchronize access to a single shared resource. A resource is termed as 'available' when the value of its binary semaphore is one and is termed as 'unavailable' when the value of its binary semaphore is 0.

A counting semaphore can have a value greater than 1. These are used to synchronize access to multiple shared resources. The integer value of these semaphores is used to denote the number of available resources.

Semaphores in Linux are of two types: System V semaphores and POSIX semaphores. The POSIX semaphores also have two subtypes: named semaphores and memory-based or unnamed semaphores.

System V-based traditional semaphores are created programmatically using the semget() function from the sys/sem.h header file.

The modern POSIX semaphores, on the other hand, are created using the sem_open() function from the semaphore.h header file.

Implementing Semaphore in Linux

There are two ways to implement semaphores in Linux: using System V IPC capabilities and the modern POSIX-compliant semaphores.

The System V-based semaphores are implemented using the semget() function. We can use semget() to either create or access an existing semaphore in Linux.

Apart from this, we also use other functions like semop() to perform operations on the semaphore. Another function used to interact with the semaphore is the semctl() function which is used to control the semaphore.

For the second type of semaphore in Linux: POSIX semaphores, we use the sem_open() function to create a semaphore.

We also have other functions to control the behaviour of a semaphore. This includes functions like sem_wait() to lock the semaphore and sem_post() to unlock it.

We close POSIX-named semaphores using sem_close() and delete them using sem_unlink() functions.

Example of Semaphore Implementation in Linux

We can implement a System V semaphore with the following code in C:

semaphore-in-linux2

In this program, we are first creating the semaphore using the code: int semid = semget(SEM_KEY, 1, IPC_CREAT | 0666);. The first argument of semget() is the identifier of the semaphore. The second argument 1 creates the semaphore. The third flag instructs the system to create a semaphore in Linux if it does not exist.

We are controlling the working of the semaphore using the semctl() function. The first call of semctl() is used to initialize the semaphore.

After the process sleeps for 60 seconds, we remove the semaphore using semctl() but passing in a 0 as an argument.

We can implement a POSIX named semaphore with the following C code:

semaphore-in-linux3

In this code, we are creating a semaphore in Linux using the sem_open() function. POSIX semaphores are also called named semaphores because we can name them as can be seen in this example. In the function, we are passing in the char array as the name for the semaphore. O_CREAT is also used to instruct the system to create a named semaphore if it does not exist.

Once the process wakes up from the 60-second sleep, we close the semaphore using the sem_close() function and then finally delete it using the sem_unlink() function.

Conclusion

  • Semaphores in Linux are a way to control access to a shared resource by multiple processes. They are simple control mechanisms which help in the Inter-Process Communication between processes.
  • In theory, they are of two types: binary semaphores which can have the values of 0 and 1 and counting semaphores which can have values greater than 1 and are used to control multiple resources.
  • In Linux, semaphores are of two other types: Older System V IPC semaphores and the modern POSIX named semaphores.
  • We use functions like semget() to open a semaphore in System V semaphores and sem_open() to open semaphores in POSIX named semaphores.