This section focuses on the Lifecycle of a semaphore: How to create it, how to finish using it, and how to remove it from the system completely.
1. Opening and Creating: sem_open
Just like opening a file, you need to “open” a semaphore before you can use it.
#include <semaphore.h>
sem_t *sem_open(const char *name, int oflag, ... /* mode_t mode, unsigned int value */ );
// Returns: Pointer to semaphore if OK, SEM_FAILED on errorKey Arguments:
name: A string identifying the semaphore.- Portability Note: Posix requires the name to start with a slash (
/) and contain no other slashes (e.g.,/mysem).
- Portability Note: Posix requires the name to start with a slash (
oflag: Flags that control the operation, exactly like file I/O:0: Just open an existing semaphore.O_CREAT: Create the semaphore if it doesn’t exist.O_CREAT | O_EXCL: Create it, but fail if it already exists (prevents race conditions).
mode&value: These are optional arguments, but required if you specifyO_CREAT.mode: Permission bits (like0644).value: The initial value of the counter (e.g., 1 for a mutex, 0 for synchronization, N for a resource pool).
Code Snippet (Creating a new semaphore):
// Open a semaphore named "/testsem", create it if missing, permissions 0644, initial value 1
sem_t *sem = sem_open("/testsem", O_CREAT | O_EXCL, 0644, 1);
if (sem == SEM_FAILED) {
// Handle error (e.g., it already exists)
}2. Closing: sem_close
When a process is finished using a semaphore, it should close it.
int sem_close(sem_t *sem);- What it does: It tells the system “this process is done using this semaphore.” It frees resources within this process.
- What it does NOT do: It does not reset the semaphore’s value to zero, nor does it remove the semaphore from the system. If another process opens
/testsemlater, it will see the value exactly where you left it (Kernel Persistence).
3. Destruction: sem_unlink
Because Named Semaphores have kernel persistence (they survive even after the creating process dies), you must explicitly delete them to clean up the system.
int sem_unlink(const char *name);- Behavior: This removes the name
/testsemfrom the system. - The “Delete-Pending” Rule: If you call
sem_unlinkwhile other processes still have the semaphore open (sem_open), the name is removed immediately (no new processes can open it). The destruction of the semaphore is delayed until the last open reference is closed.
Summary of the Lifecycle
The book highlights this flow to avoid “resource leaks” where semaphores pile up in the system:
- Server:
sem_open(..., O_CREAT, ...)Creates it. - Client:
sem_open(...)Connects to it. - Clients/Server: Use
sem_wait/sem_post(Covered in next section). - Clients/Server:
sem_close(...)Disconnects. - Server (usually):
sem_unlink(...)Marks for destruction.