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 error

Key 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).
  • 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 specify O_CREAT.
    • mode: Permission bits (like 0644).
    • 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 /testsem later, it will see the value exactly where you left it (Kernel Persistence).

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 /testsem from the system.
  • The “Delete-Pending” Rule: If you call sem_unlink while 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:

  1. Server: sem_open(..., O_CREAT, ...) Creates it.
  2. Client: sem_open(...) Connects to it.
  3. Clients/Server: Use sem_wait / sem_post (Covered in next section).
  4. Clients/Server: sem_close(...) Disconnects.
  5. Server (usually): sem_unlink(...) Marks for destruction.