oreilly.comSafari Books Online.Conferences.


Semaphores in Linux
Pages: 1, 2, 3, 4, 5, 6

NOTE: System V semaphores are controlled by the user, but can be a problem to the developer is the permissions on the semaphore. The structure that maintains this information is struct semid_ds.

struct semid_ds
  struct  ipc_perm sem_per; /* operation's permission structure */
  struct  sem * sem_base; /* pointer to first sem in a set */
  ushort sem_nsems; /* number of sem in a set */
  time_t sem_otime; /*time of last semop */
  time_t sem_ctime; /* time of last change */

For every set of semaphores in the system, the kernel maintains a structure of information that is defined in sys/ipc.h. To get the details of the semaphore set shown above, the IPC_STAT flag is used and a pointer to structure semid_ds is passed. The member variable that gets and sets the permissions is sem_per. Let's see a simple example:

#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>
#include <sys/sem.h>

int main()
  int semid;
  struct semid_ds status;

  semid = semget(( key_t )0x20,10,IPC_CREAT|0666);
  if(semid == -1)
      perror("sem creation failed:Reason");
  //get the permission details
  printf("owners uid is %u\n",status.sem_perm.uid);
  printf("group uid is %u\n",status.sem_perm.gid);
  printf("Access mode is %c\n",status.sem_perm.mode);

  //set the permissions details 
  status.sem_perm.uid = 102;
  status.sem_perm.gid = 102;
  status.sem_perm.mode = 0444;

  return 1;

Note that the setting of permission is only allowed if the new permission set is a subset of the original permission, and not a superset.

POSIX Semaphores

The potential learning curve of System V semaphores is much higher when compared to POSIX semaphores. This will be more understandable after you go through this section and compare it to what you learned in the previous section.

To start with, POSIX comes with simple semantics for creating, initializing, and performing operations on semaphores. They provide an efficient way to handle interprocess communication. POSIX comes with two kinds of semaphores: named and unnamed semaphores.

Named Semaphores

If you look in the man pages, you'll see that a named semaphore is identified by a name, like a System V semaphore, and, similarly, the semaphores have kernel persistence. This implies that these semaphores, like System V, are system-wide and limited to the number that can be active at any one time. The advantage of named semaphores is that they provide synchronization between unrelated process and related process as well as between threads.

A named semaphore is created by calling following function:

sem_t *sem_open(const char *name,  int oflag, mode_t mode , int value);
Name of the semaphore to be identified.
Is set to O_CREAT for creating a semaphore (or with O_EXCL if you want the call to fail if it already exists).
Controls the permission setting for new semaphores.
Specifies the initial value of the semaphore.

A single call creates the semaphore, initializes it, and sets permissions on it, which is quite different from the way System V semaphores act. It is much cleaner and more atomic in nature. Another difference is that the System V semaphore identifies itself by means of type int (similar to a fd returned from open()), whereas the sem_open function returns type sem_t, which acts as an identifier for the POSIX semaphores.

From here on, operations will only be performed on semaphores. The semantics for locking semaphores is:

int  sem_wait(sem_t *sem);

This call locks the semaphore if the semaphore count is greater than zero. After locking the semaphore, the count is reduced by 1. If the semaphore count is zero, the call blocks.

The semantics for unlocking a semaphore is:

int  sem_post(sem_t *sem);

This call increases the semaphore count by 1 and then returns.

Once you're done using a semaphore, it is important to destroy it. To do this, make sure that all the references to the named semaphore are closed by calling the sem_close() function, then just before the exit or within the exit handler call sem_unlink() to remove the semaphore from the system. Note that sem_unlink() would not have any effect if any of the processes or threads reference the semaphore.

Unnamed Semaphores

Again, according to the man pages, an unnamed semaphore is placed in a region of memory that is shared between multiple threads (a thread-shared semaphore) or processes (a process-shared semaphore). A thread-shared semaphore is placed in a region where only threads of an process share them, for example a global variable. A process-shared semaphore is placed in a region where different processes can share them, for example something like a shared memory region. An unnamed semaphore provides synchronization between threads and between related processes and are process-based semaphores.

The unnamed semaphore does not need to use the sem_open call. Instead this one call is replaced by the following two instructions:

  sem_t semid;
  int sem_init(sem_t *sem, int pshared, unsigned  value);
This argument indicates whether this semaphore is to be shared between the threads of a process or between processes. If pshared has value 0, then the semaphore is shared between the threads of a process. If pshared is non-zero, then the semaphore is shared between processes.
The value with which the semaphore is to be initialized.

Once the semaphore is initialized, the programmer is ready to operate on the semaphore, which is of type sem_t. The operations to lock and unlock the semaphore remains as shown previously: sem_wait(sem_t *sem) and sem_post(sem_t *sem). To delete a unnamed semaphore, just call the sem_destroy function.

The last section of this article has a simple worker-consumer demo that has been developed by using a POSIX semaphore.

System V Semaphores versus POSIX Semaphores

There are a number of differences between System V and POSIX semaphores.

  • One marked difference between the System V and POSIX semaphore implementations is that in System V you can control how much the semaphore count can be increased or decreased; whereas in POSIX, the semaphore count is increased and decreased by 1.
  • POSIX semaphores do not allow manipulation of semaphore permissions, whereas System V semaphores allow you to change the permissions of semaphores to a subset of the original permission.
  • Initialization and creation of semaphores is atomic (from the user's perspective) in POSIX semaphores.
  • From a usage perspective, System V semaphores are clumsy, while POSIX semaphores are straight-forward
  • The scalability of POSIX semaphores (using unnamed semaphores) is much higher than System V semaphores. In a user/client scenario, where each user creates her own instances of a server, it would be better to use POSIX semaphores.
  • System V semaphores, when creating a semaphore object, creates an array of semaphores whereas POSIX semaphores create just one. Because of this feature, semaphore creation (memory footprint-wise) is costlier in System V semaphores when compared to POSIX semaphores.
  • It has been said that POSIX semaphore performance is better than System V-based semaphores.
  • POSIX semaphores provide a mechanism for process-wide semaphores rather than system-wide semaphores. So, if a developer forgets to close the semaphore, on process exit the semaphore is cleaned up. In simple terms, POSIX semaphores provide a mechanism for non-persistent semaphores.

Pages: 1, 2, 3, 4, 5, 6

Next Pagearrow

Linux Online Certification

Linux/Unix System Administration Certificate Series
Linux/Unix System Administration Certificate Series — This course series targets both beginning and intermediate Linux/Unix users who want to acquire advanced system administration skills, and to back those skills up with a Certificate from the University of Illinois Office of Continuing Education.

Enroll today!

Linux Resources
  • Linux Online
  • The Linux FAQ
  • Linux Kernel Archives
  • Kernel Traffic

  • Sponsored by: