Synchronization
  • Introduction
  • Race Condition
    • Too Much Milk Problem
  • Mutual Exclusion
    • Shared Output
  • Semaphore in C
  • Too Much Milk: Use semaphore
  • Shared Output: Use semaphore
  • Traffic Control Problem
  • Traffic Control: Solution
  • Shared Memory
Powered by GitBook
On this page

Was this helpful?

Semaphore in C

Named Semaphore

POSIX named semaphore APIs we use in this lab are shown in the table below. You can look up the manual pages for details. semaphore.c shows how to use these functions to create, operate and remove named semaphore. Try it and make sure you understand it. Note that programs using the POSIX semaphores API must be compiled with -lpthread to link against the library. So you need to compile semaphore.c like this:

gcc semaphore.c -lpthread -o semaphore

Function

Description

sem_open

opens/creates a named semaphore for use by a process

sem_wait

locks a semaphore

sem_post

unlocks a semaphore

sem_close

deallocates the specified named semaphore

sem_unlink

removes the specified named semaphore

/*semaphore.c*/
#include <fcntl.h> /* For O_* constants */
#include <semaphore.h>
#include <stdio.h>
#include <sys/stat.h> /* For mode constants */

int main(int argc, char *argv[]) {
    char *name = "my_semaphore";
    int VALUE = 2;
    sem_t *sema;
    // If semaphore with name does not exist, then create it with VALUE
    printf("Open or Create a named semaphore, %s, its value is %d\n", name, VALUE);
    sema = sem_open(name, O_CREAT, 0666, VALUE);
    // wait on semaphore sema and decrease it by 1
    sem_wait(sema);
    printf("Decrease semaphore by 1\n");
    // add semaphore sema by 1
    sem_post(sema);
    printf("Add semaphore by 1\n");
    // Before exit, you need to close semaphore and unlink it, when all  processes have
    // finished using the semaphore, it can be removed from the system using sem_unlink
    sem_close(sema);
    sem_unlink(name);
    return 0;
}

Unnamed Semaphore

POSIX semaphores are available in two flavors: named and unnamed. They differ in how they are created and destroyed but otherwise work the same.

Unnamed semaphores exist in memory only and only the processes having access to that piece of memory can use the semaphores. This means they can be used only by threads in the same process or threads in different processes but have mapped the same memory into their address spaces. Named semaphores, in contrast, are accessed by name and can be used by threads in any process that knows the name.

When we want to use POSIX semaphores within a single process, it is easier to use unnamed semaphores. This only changes the way we create and destroy the semaphore. To create an unnamed semaphore, we call the sem_init()function.

#include <semaphore.h>

int sem_init(sem_t *sem, int pshared, unsigned int value);

The pshared argument indicates if we plan to use the semaphore with multiple processes. If we just want to use the semaphore in a single process, set it to zero. The value argument specifies the initial value of the semaphore.

Instead of returning a pointer to the semaphore like sem_open() does, we need to declare a variable of type sem_t and pass its address to sem_init() for initialization. After initializing unnamed semaphore using sem_init() function, the sem_wait() and sem_post() functions can work as usual.

When we are done using the unnamed semaphore, we can destroy it by calling the sem_destroy() function.

#include <semaphore.h>

int sem_destroy(sem_t *sem);

After calling sem_destroy(), we can't use any of the semaphore functions with sem unless we reinitialize it by calling sem_init() again.

PreviousShared OutputNextToo Much Milk: Use semaphore

Last updated 1 month ago

Was this helpful?