What is a Semaphore?
A semaphore is a kernel-maintained integer variable used for synchronization. Its value is always non-negative (zero or greater). Two fundamental operations are performed on it:
- Wait (P / decrement): If the semaphore value is greater than zero, decrement it and continue. If it is zero, block (sleep) until it becomes greater than zero.
- Post (V / increment): Increment the semaphore value. If any process or thread is blocked waiting on this semaphore, wake one of them up.
The original concepts come from Dutch computer scientist Edsger Dijkstra. He called the operations P (proberen = to test) and V (verhogen = to increment). In POSIX, these are sem_wait() and sem_post().
Two Types of POSIX Semaphores
POSIX provides two kinds of semaphores. They use the same operations (sem_wait, sem_post, etc.) but differ in how they are created and where they live.
| Property | Named Semaphore | Unnamed Semaphore |
|---|---|---|
| Identity | Has a filesystem name like /mysem |
No name, lives in memory (a variable) |
| Create / Open | sem_open() |
sem_init() |
| Destroy | sem_close() + sem_unlink() |
sem_destroy() |
| Sharing | Any unrelated process by name | Must be in shared memory for processes; global variable for threads |
| Persistence | Persists until explicitly unlinked | Lives only as long as the memory it is in |
Where Named Semaphores Live
On Linux, named semaphores are implemented as small files inside a special in-memory filesystem. When you call sem_open("/mysem", ...), Linux creates a file at:
/dev/shm/sem.mysem
You can see this with ls /dev/shm/. The /dev/shm mount point is a tmpfs filesystem — it lives entirely in RAM and is cleared on reboot. The semaphore name must start with a forward slash and contain no other slashes. Portable programs use exactly one slash at the start.
sem_open("/s")/dev/shm/sem.s
value = 1
sem_open("/s")The sem_t Data Type
The type sem_t is defined in <semaphore.h>. It is an opaque type — you should never try to read or write its internals directly. Always use the POSIX API functions.
- For named semaphores,
sem_open()returns a pointer tosem_t. - For unnamed semaphores, you declare a
sem_tvariable and pass its address tosem_init().
#include <semaphore.h>
/* Named semaphore – pointer returned by sem_open */
sem_t *named_sem;
/* Unnamed semaphore – you own the variable */
sem_t unnamed_sem;
Required Header and Linking
Every program using POSIX semaphores must:
- Include
#include <semaphore.h> - Link against the POSIX real-time library: compile with
-lpthread(on Linux, semaphore functions are in the pthreads library)
gcc myprog.c -o myprog -lpthread
On some older Linux systems you may also need -lrt. On modern Linux with glibc, -lpthread is sufficient for all POSIX semaphore functions.
Binary Semaphore vs Counting Semaphore
POSIX semaphores support two usage patterns:
Value is only 0 or 1. Acts like a mutex. One resource to protect, one holder at a time.
sem_init(&s, 0, 1); /* initial = 1 */
Value can be any non-negative integer. Controls access to a pool of N resources (e.g., 5 database connections).
sem_init(&s, 0, 5); /* pool of 5 */
Complete Minimal Example
Here is the simplest possible POSIX semaphore program — two threads, one semaphore, used as a signal from thread 1 to thread 2.
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
sem_t sem; /* unnamed semaphore, shared between threads */
void *thread_wait(void *arg)
{
printf("Thread: waiting for signal...\n");
sem_wait(&sem); /* block until value > 0 */
printf("Thread: got signal, continuing.\n");
return NULL;
}
int main(void)
{
pthread_t tid;
sem_init(&sem, 0, 0); /* pshared=0 (threads), initial value=0 */
pthread_create(&tid, NULL, thread_wait, NULL);
sleep(2); /* simulate some work */
printf("Main: posting semaphore.\n");
sem_post(&sem); /* increment, unblock the waiting thread */
pthread_join(tid, NULL);
sem_destroy(&sem);
return 0;
}
Compile and run:
gcc minimal_sem.c -o minimal_sem -lpthread
./minimal_sem
# Output:
# Thread: waiting for signal...
# Main: posting semaphore.
# Thread: got signal, continuing.
