Named Semaphores

To work with a named semaphore, we employ the following functions:

SUSv3 doesn’t specify how named semaphores are to be implemented. Some UNIX implementations create them as files in a special location in the standard file system. On Linux, they are created as small POSIX shared memory objects with names of the form sem.name, in a dedicated tmpfs file system (A Virtual Memory File System: tmpfs) mounted under the directory /dev/shm. This file system has kernel persistence--the semaphore objects that it contains will persist, even if no process currently has them open, but they will be lost if the system is shut down.

Named semaphores are supported on Linux since kernel 2.6.

The sem_open() function creates and opens a new named semaphore or opens an existing semaphore.

#include <fcntl.h>            /* Defines O_* constants */
#include <sys/stat.h>         /* Defines mode constants */
#include <semaphore.h>

sem_t *sem_open(const char *name, int oflag, ...
                /* mode_t mode, unsigned int value */ );

Note

Returns pointer to semaphore on success, or SEM_FAILED on error

The name argument identifies the semaphore. It is specified according to the rules given in Section 51.1.

The oflag argument is a bit mask that determines whether we are opening an existing semaphore or creating and opening a new semaphore. If oflag is 0, we are accessing an existing semaphore. If O_CREAT is specified in oflag, then a new semaphore is created if one with the given name doesn’t already exist. If oflag specifies both O_CREAT and O_EXCL, and a semaphore with the given name already exists, then sem_open() fails.

If sem_open() is being used to open an existing semaphore, the call requires only two arguments. However, if O_CREAT is specified in flags, then two further arguments are required: mode and value. (If the semaphore specified by name already exists, then these two arguments are ignored.) These arguments are as follows:

Regardless of whether we are creating a new semaphore or opening an existing semaphore, sem_open() returns a pointer to a sem_t value, and we employ this pointer in subsequent calls to functions that operate on the semaphore. On error, sem_open() returns the value SEM_FAILED. (On most implementations, SEM_FAILED is defined as either ((sem_t *) 0) or ((sem_t *) -1); Linux defines it as the former.)

SUSv3 states that the results are undefined if we attempt to perform operations (sem_post(), sem_wait(), and so on) on a copy of the sem_t variable pointed to by the return value of sem_open(). In other words, the following use of sem2 is not permissible:

sem_t *sp, sem2
sp = sem_open(...);
sem2 = *sp;
sem_wait(&sem2);

When a child is created via fork(), it inherits references to all of the named semaphores that are open in its parent. After the fork(), the parent and child can use these semaphores to synchronize their actions.

The program in Example 53-1 provides a simple command-line interface to the sem_open() function. The command format for this program is shown in the usageError() function.

The following shell session log demonstrates the use of this program. We first use the umask command to deny all permissions to users in the class other. We then exclusively create a semaphore and examine the contents of the Linux-specific virtual directory that contains named semaphores.

$ umask 007
$ ./psem_create -cx /demo 666             666 means read+write for all users
$ ls -l /dev/shm/sem.*
-rw-rw----  1 mtk users 16 Jul  6 12:09 /dev/shm/sem.demo

The output of the ls command shows that the process umask overrode the specified permissions of read plus write for the user class other.

If we try once more to exclusively create a semaphore with the same name, the operation fails, because the name already exists.

$ ./psem_create -cx /demo 666
ERROR [EEXIST File exists] sem_open       Failed because of O_EXCL

When a process opens a named semaphore, the system records the association between the process and the semaphore. The sem_close() function terminates this association (i.e., closes the semaphore), releases any resources that the system has associated with the semaphore for this process, and decreases the count of processes referencing the semaphore.

#include <semaphore.h>

int sem_close(sem_t *sem);

Note

Returns 0 on success, or -1 on error

Open named semaphores are also automatically closed on process termination or if the process performs an exec().

Closing a semaphore does not delete it. For that purpose, we need to use sem_unlink().

The sem_unlink() function removes the semaphore identified by name and marks the semaphore to be destroyed once all processes cease using it (this may mean immediately, if all processes that had the semaphore open have already closed it).

#include <semaphore.h>

int sem_unlink(const char *name);

Note

Returns 0 on success, or -1 on error

Example 53-2 demonstrates the use of sem_unlink().