Monday, June 15, 2009

Semaphore - Linux Lab

Posted by Sarjukottapuram

SEMAPHORE
Theory
Semaphores are a programming construct designed by E. W. Dijkstra in the late 1960s. Dijkstra's model was the operation of railroads: consider a stretch of railroad in which there is a single track over which only one train at a time is allowed. Guarding this track is a semaphore. A train must wait before entering the single track until the semaphore is in a state that permits travel. When the train enters the track, the semaphore changes state to prevent other trains from entering the track. A train that is leaving this section of track must again change the state of the semaphore to allow another train to enter. In the computer version, a semaphore appears to be a simple integer. A process (or a thread) waits for permission to proceed by waiting for the integer to become 0. The signal if it proceeds signals that this by performing incrementing the integer by 1. When it is finished, the process changes the semaphore's value by subtracting one from it.
Semaphore is a variable that can take only the values 0 and 1, binary semaphore. This is the most common form. Semaphore that can take many positive values are called general semaphores.
The definition of P and V are surprisingly simple. Suppose we have semaphore variable sv. The two operations are defined as follows:
P(sv) – If sv is greater than zero, decrement sv, if sv is zero, suspend execution of this process.
V(sv) – If some other process has been suspend waiting for sv, make it resume execution. If no process is suspended waiting for sv, Increment sv.
Semaphores let processes query or alter status information. They are often used to monitor and control the availability of system resources such as shared memory segments.
POSIX semaphores are much lighter weight than are System V semaphores. A POSIX semaphore structure defines a single semaphore, not an array of up to twenty five semaphores. The POSIX semaphore functions are:
sem_open() -- Connects to, and optionally creates, a named semaphore
sem_init() -- Initializes a semaphore structure (internal to the calling program, so not a named semaphore).
sem_close() -- Ends the connection to an open semaphore.
sem_unlink() -- Ends the connection to an open semaphore and causes the semaphore to be removed when the last process closes it.
sem_destroy() -- Initializes a semaphore structure (internal to the calling program, so not a named semaphore).
sem_getvalue() -- Copies the value of the semaphore into the specified integer.
sem_wait(), sem_trywait() -- Blocks while the semaphore is held by other processes or returns an error if the semaphore is held by another process.
sem_post() -- Increments the count of the semaphore.
All POSIX semaphore functions and types are prototyped or defined in semaphore.h. To define a semaphore object, use
sem_t sem_name;
To initialize a semaphore, use sem_init():
int sem_init(sem_t *sem, int pshared, unsigned int value);
• sem points to a semaphore object to initialize
• pshared is a flag indicating whether or not the semaphore should be shared with fork()ed processes. LinuxThreads does not currently support shared semaphores
• value is an initial value to set the semaphore to
Example of use:
sem_init(&sem_name, 0, 10);
________________________________________
To wait on a semaphore, use sem_wait:
int sem_wait(sem_t *sem);
Example of use:
sem_wait(&sem_name);
• If the value of the semaphore is negative, the calling process blocks; one of the blocked processes wakes up when another process calls sem_post.
________________________________________
To increment the value of a semaphore, use sem_post:
int sem_post(sem_t *sem);
Example of use:
sem_post(&sem_name);
• It increments the value of the semaphore and wakes up a blocked process waiting on the semaphore, if any.
________________________________________
To find out the value of a semaphore, use
int sem_getvalue(sem_t *sem, int *valp);
• gets the current value of sem and places it in the location pointed to by valp
Example of use:
int value;
sem_getvalue(&sem_name, &value);
printf("The value of the semaphors is %d\n", value);
________________________________________
To destroy a semaphore, use
int sem_destroy(sem_t *sem);
• destroys the semaphore; no threads should be waiting on the semaphore if its destruction is to succeed.
Example of use:
sem_destroy(&sem_name);
________________________________________
Program
/* Program to demonstrate the usage of semaphore variable in controlling the access to specific resources.
* This program contains two functions which display their own messages.
* The display is suitably controlled by the use of semaphore variable.
* It is a program in which a semaphore variable is shared between the main function and a thread function.
* This module can be compiled using 'cc semaphore1.c -lpthread' and executed './a.out'
//inculsion part.
#include
#include
#include
//function prototype for the thread function.
void * display_function();
//global semaphore variable to be shared.
sem_t sem_var;
int main()
{
pthread_t tid;
pthread_attr_t attr;
int i;
//initialising the semaphore variable with an initial value 0 (third arguement.)
sem_init(&sem_var,0,0);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
pthread_create(&tid,&attr,display_function,NULL);
for(i=0;i<5;i++)
{
printf("\n Displaying from the main function:\t%d\n",i+1);
//waiting for the resources.
sem_wait(&sem_var);
}
//destroying the semaphore variable.
sem_destroy(&sem_var);
}
void * display_function()
{
int i;
for(i=0;i<5;i++)
{
printf("\n***** Displaying from the thread function.:\t%d\n",i+1);
//releasing resources.
sem_post(&sem_var);
sleep(1);
}
}
SERIALISABILITY PROBLEM.
(By using Semaphore Variable)
Program
* This program uses a variable 'data' whose value is used by two thread function.
* But the condition is that when a function uses it no other function should use it.
* This problem is tackled by definig two thread function and suitably making them access it by the use of semaphore variable.
* This module can be compiled using 'cc semaphore2.c -lpthread' and executed './a.out'
//inculsion part.
#include
#include
#include
//prototype for thread functions.
void * thread_function1();
void * thread_function2();
//global variables.
int data=0,end=0;
//global semaphore variables.
sem_t sem_var;
int main()
{
pthread_t t1,t2;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
sem_init(&sem_var,0,1);
pthread_create(&t1,&attr,thread_function1,NULL);
pthread_create(&t2,&attr,thread_function2,NULL);
while(end!=2)
{
}
printf("\n\t****** The value of DATA is:\t%d ******\n",data);
}
//definition of first thread function.
void * thread_function1()
{
int a;
printf("\nEntered into thread function:1\n");
printf("\nThread function:1 waiting to gain access\n");
sleep(1);
sem_wait(&sem_var);
printf("\nAccess gained by thread function:1\n");
printf("\nThread function:1 using the value of 'DATA' \n");
a=data;
a=a+1;
data=a;
sem_post(&sem_var);
printf("\nResources released by thread function:1\n");
end++;
}
//definition of second thread function.
void * thread_function2()
{
int b;
printf("\nEntered into thread function:2\n");
printf("\nThread function:2 waiting to gain access\n");
sleep(1);
sem_wait(&sem_var);
printf("\nAccess gained by thread function:2\n");
printf("\nThread function:2 using the value of 'DATA' \n");
b=data;
b=b+1;
data=b;
sem_post(&sem_var);
printf("\nResources released by thread function:2\n");
end++;
}

0 comments:

Post a Comment