Saturday, December 29, 2012

Using semaphore to synchronize the multiple thread using c on linux/fedora

Semaphore is a new type of variable introduced by E. W. Dijkstra. You may learn about semaphores in university. It is used to solve the Producer-Consumer Problem in Operation system design which I have learn in books "Modern Operating Systems " (second edition) by Andrew S. Tanenbaum. In that books the algorithm for semaphore is clearly defined and easy to understand. But I was always curious about that "Does this type of problem occur on our program?" rather than operating system design and "Where can I use it?". When I begin to learn linux programming I found the semaphore function under <semaphore.h> header and example program where semaphore is used to synchronize the thread.
In this article we look at the simplest type of semaphore, a binary semaphore that takes only values 0 or 1. There is also a more general semaphore that takes a wider range of values. Normally, semaphores are used to protect a piece of code so that only one thread of execution can run it at any one time.The semaphore functions do not start with pthread_,as most thread-specific functions do,but with sem_. Four basic semaphore functions are used in threads. They are all quite simple.

A semaphore is created with the sem_init funtion, which is declared as follows.
#include<semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);


This function initializes a semaphore objuect pointed to by sem, sets its sharing option and gives it an initial integer value. The pshared parameter controls the type of semaphore. If the value of pshared is 0, the semaphore is local to the current process. Otherwise, the semaphore may be shared between process.Here we passed the 0 value.
The next pair of functions controls the value of the semaphore and is declared as follows.
#include <semaphore.h>
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);

These both take a pointer to the semaphore object initialized by a call to sem_init.
The last semaphore function is sem_destroy. This function tides up the semaphore when you have finished with it. It is declared as follows:

#include <semaphore.h>
int sem_destroy(sem_t *sem);

Again, this function takes a pointer to a semaphore and tides up any resources that it may haver. If you attempt to destroy a semaphore for which some thread is waiting, you will get an error.
Like most Linux functions,these functions all return 0 on success.
 //semaphore.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>

void *thread_function(void *arg);
sem_t bin_sem;

#define WORK_SIZE 1024
char work_area[WORK_SIZE];

int main() {
    int res;
    pthread_t a_thread;
    void *thread_result;

    res = sem_init(&bin_sem, 0, 0);
    if (res != 0) {
        perror("Semaphore initialization failed");
        exit(EXIT_FAILURE);
    }
    res = pthread_create(&a_thread, NULL, thread_function, NULL);
    if (res != 0) {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
    printf("Input some text. Enter 'end' to finish\n");
    while(strncmp("end", work_area, 3) != 0) {
        fgets(work_area, WORK_SIZE, stdin);
        sem_post(&bin_sem);
    }
    printf("\nWaiting for thread to finish...\n");
    res = pthread_join(a_thread, &thread_result);
    if (res != 0) {
        perror("Thread join failed");
        exit(EXIT_FAILURE);
    }
    printf("Thread joined\n");
    sem_destroy(&bin_sem);
    exit(EXIT_SUCCESS);
}

void *thread_function(void *arg) {
    sem_wait(&bin_sem);
    while(strncmp("end", work_area, 3) != 0) {
        printf("You input %d characters\n", strlen(work_area) -1);
        sem_wait(&bin_sem);
    }
    pthread_exit(NULL);
}  
You can compile this program as per the instruction of my previous article about thread .

No comments:

Post a Comment