What Are Named Semaphores?
Named semaphores are identified by a name in the filesystem. Any unrelated process that knows the name and has the right permissions can open and use the semaphore. This makes named semaphores the right choice for inter-process synchronization where the processes are not related by fork.
The lifecycle of a named semaphore is: create/open → use → close → unlink.
sem_open() – Create or Open a Named Semaphore
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
sem_t *sem_open(const char *name, int oflag, ...
/* mode_t mode, unsigned int value */ );
/* Returns: pointer to semaphore on success, SEM_FAILED on error */
sem_open() either creates a new semaphore or opens an existing one, depending on the flags passed.
| Parameter | Description |
|---|---|
name |
Semaphore name. Must start with /. No further slashes. Example: "/counter" |
oflag |
O_CREAT to create if not exists. O_CREAT | O_EXCL to fail if it already exists. 0 to open existing only. |
mode |
Permission bits (like file permissions, e.g. 0600). Only used when O_CREAT is set. |
value |
Initial value of the semaphore. Only used when O_CREAT is set and the semaphore is actually created. |
Flag Behavior
| O_CREAT | O_EXCL | Semaphore Exists? | Result |
|---|---|---|---|
| No | No | Yes | Opens existing semaphore |
| No | No | No | Error: ENOENT |
| Yes | No | Yes | Opens existing (ignores value/mode) |
| Yes | No | No | Creates new semaphore with value |
| Yes | Yes | Yes | Error: EEXIST |
| Yes | Yes | No | Creates new semaphore with value |
Example: Creating a Named Semaphore
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
int main(void)
{
sem_t *sem;
/* Create semaphore /myapp_lock with initial value 1
Fail if it already exists (O_EXCL) */
sem = sem_open("/myapp_lock", O_CREAT | O_EXCL, 0600, 1);
if (sem == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
printf("Semaphore created successfully.\n");
/* ... use the semaphore ... */
sem_close(sem); /* close this process's handle */
sem_unlink("/myapp_lock"); /* remove the semaphore name */
return 0;
}
sem_close() – Close a Named Semaphore
#include <semaphore.h>
int sem_close(sem_t *sem);
/* Returns: 0 on success, -1 on error */
sem_close() closes the calling process’s association with the named semaphore. It is analogous to close() for file descriptors. Important points:
- The semaphore is not removed from the system. It still exists for other processes.
- Any locks held by this process on the semaphore are released.
- If the process exits without calling
sem_close(), the kernel automatically closes all semaphores opened by that process. - You must still call
sem_unlink()separately to remove the semaphore from the filesystem.
sem_unlink() – Remove a Named Semaphore
#include <semaphore.h>
int sem_unlink(const char *name);
/* Returns: 0 on success, -1 on error */
sem_unlink() removes the semaphore name from the filesystem (i.e., deletes /dev/shm/sem.name). The semaphore itself is not destroyed until all processes that have it open call sem_close() — this is the same deferred destruction used by unlink() for files.
Named Semaphore Lifecycle
Complete Cross-Process Example
Two programs share a named semaphore. The server creates it; the client opens it. The semaphore acts as a binary mutex protecting a shared counter in shared memory.
server.c – Creates the semaphore
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <unistd.h>
#define SEM_NAME "/demo_sem"
int main(void)
{
sem_t *sem;
/* Remove stale semaphore if present */
sem_unlink(SEM_NAME);
/* Create with initial value 1 (binary semaphore) */
sem = sem_open(SEM_NAME, O_CREAT | O_EXCL, 0666, 1);
if (sem == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
printf("Server: semaphore created. Waiting 10 seconds...\n");
sleep(10);
printf("Server: cleaning up.\n");
sem_close(sem);
sem_unlink(SEM_NAME);
return 0;
}
client.c – Opens the existing semaphore
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.h>
#define SEM_NAME "/demo_sem"
int main(void)
{
sem_t *sem;
/* Open existing semaphore (no O_CREAT) */
sem = sem_open(SEM_NAME, 0);
if (sem == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
printf("Client: acquired semaphore, locking...\n");
sem_wait(sem); /* lock */
printf("Client: inside critical section.\n");
sleep(2);
sem_post(sem); /* unlock */
printf("Client: released semaphore.\n");
sem_close(sem);
return 0;
}
Run in two terminals:
# Terminal 1
gcc server.c -o server -lpthread && ./server
# Terminal 2 (while server is running)
gcc client.c -o client -lpthread && ./client
Common Errors
| errno | Cause | Fix |
|---|---|---|
ENOENT |
Opening a semaphore that does not exist (no O_CREAT) | Add O_CREAT or ensure server created it first |
EEXIST |
O_CREAT | O_EXCL but semaphore already exists | Call sem_unlink first, or use O_CREAT without O_EXCL |
EINVAL |
Name has bad format, or value > SEM_VALUE_MAX | Name must start with / and have no other / |
EACCES |
Permission denied on open | Check mode bits passed at creation |
