Definition
Binary Semaphores can assume only the value 0 or the value 1 counting semaphores also called general semaphores can assume only nonnegative values.
The P (or wait or sleep or down) operation on semaphores S, written as P(S) or wait (S), operates as follows:
P(S): IF S > 0
THEN S := S - 1
ELSE (wait on S)
The V (or signal or wakeup or up) operation on semaphore S, written as V(S) or signal (S), operates as follows:
V(S): IF (one or more process are waiting on S)
THEN (let one of these processes proceed)
ELSE S := S +1
Operations P and V are done as single, indivisible, atomic action. It is guaranteed that once a semaphore operations has stared, no other process can access the semaphore until operation has completed. Mutual exclusion on the semaphore, S, is enforced within P(S) and V(S).
If several processes attempt a P(S) simultaneously, only process will be allowed to proceed. The other processes will be kept waiting, but the implementation of P and V guarantees that processes will not suffer indefinite postponement.
Semaphores solve the lost-wakeup problem.
Producer-Consumer Problem Using Semaphores
The Solution to producer-consumer problem uses three semaphores, namely, full, empty and mutex.
The semaphore 'full' is used for counting the number of slots in the buffer that are full. The 'empty' for counting the number of slots that are empty and semaphore 'mutex' to make sure that the producer and consumer do not access modifiable shared section of the buffer simultaneously.
Initialization
Set full buffer slots to 0.
i.e., semaphore Full = 0.
Set empty buffer slots to N.
i.e., semaphore empty = N.
For control access to critical section set mutex to 1.
i.e., semaphore mutex = 1.
Producer ( )
WHILE (true)
produce-Item ( );
P (empty);
P (mutex);
enter-Item ( )
V (mutex)
V (full);
Consumer ( )
WHILE (true)
P (full)
P (mutex);
remove-Item ( );
V (mutex);
V (empty);
consume-Item (Item)
An Example:-
#include<sys/types.h>
#include<stdio.h>
#include<sys/ipc.h>
#include<unistd.h>
#include<sys/sem.h>
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[10]; /* message data */
};
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
struct buffer
{
unsigned short sem_num; /* semaphore number */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
};
int main(int argc, char* argv[])
{
struct msgbuf buf;
struct buffer buf1;
union semun sem;
int msg_id=msgget((key_t)2341,IPC_CREAT|IPC_EXCL);
if(msg_id<0)
{
printf("Already exists\n");
msg_id=msgget((key_t)2341,0666);
if(msg_id<0)
{
printf("handle error\n");
return 0;
}
}
////////////////////
int sem_id=semget((key_t)6001,1,IPC_CREAT|IPC_EXCL);
if(sem_id<0)
{
printf("already used semaphore\n");
sem_id=semget((key_t)6001,1,0666);
if(sem_id<0)
{
printf("error in getting semaphore\n");
return 0;
}
}
//sem.val=1;
//semctl(sem_id,0,SETVAL,sem);
sem.val=0;
semctl(sem_id,0,SETVAL,sem);
///////////////////////////
buf.mtype=atoi(argv[1]);
strcpy(buf.mtext,"test it");
int ret=msgsnd(msg_id,&buf,sizeof(buf.mtext),0);
if(ret<=0)
printf("msg sndng error%d\n",ret);
return 0;
}
Creating Reader 1
#include<sys/types.h>
#include<stdio.h>
#include<sys/ipc.h>
#include<unistd.h>
#include<sys/sem.h>
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[10]; /* message data */
};
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
struct buffer
{
unsigned short sem_num; /* semaphore number */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
};
int main()
{
struct buffer buf1;
union semun sem;
struct msgbuf buf;
int msg_id=msgget((key_t)2341,IPC_CREAT|IPC_EXCL);
if(msg_id<0)
{
printf("Already exists\n");
msg_id=msgget((key_t)2341,0666);
if(msg_id<0)
{
printf("handle error\n");
return 0;
}
}
int ret=msgrcv(msg_id,&buf,sizeof(buf.mtext),10,0);
if(ret<=0)
printf("msg sndng error\n");
else
printf("%s\n",buf.mtext);
int sem_id=semget((key_t)6001,1,IPC_CREAT|IPC_EXCL);
if(sem_id<0)
{
printf("already used semaphore\n");
sem_id=semget((key_t)6001,1,0666);
if(sem_id<0)
{
printf("error in getting semaphore\n");
return 0;
}
}
//sem.val=1;
//semctl(sem_id,0,SETVAL,sem);
buf1.sem_num=0;
buf1.sem_flg=SEM_UNDO;
buf1.sem_op=1;
semop(sem_id,&buf1,1);
return 0;
}
Creating Reader 2
#include<sys/types.h>
#include<stdio.h>
#include<sys/sem.h>
#include<sys/ipc.h>
#include<unistd.h>
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[10]; /* message data */
};
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
struct buffer
{
unsigned short sem_num; /* semaphore number */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
};
int main()
{
struct msgbuf buf; //buffer for message queue
struct buffer buf1; //buffer for semaphore
union semun sem; //union for semaphore
int msg_id=msgget((key_t)2341,IPC_CREAT|IPC_EXCL); //taking the message queue
int sem_id=semget((key_t)6001,1,IPC_CREAT|IPC_EXCL); //taking the semaphore
if(sem_id<0)
{
printf("already used semaphore\n");
sem_id=semget((key_t)6001,1,0666);
if(sem_id<0)
{
printf("error in getting semaphore\n");
return 0;
}
}
//sem.val=0; //initialize the semaphore
//semctl(sem_id,0,SETVAL,sem);
buf1.sem_num=0;
buf1.sem_flg=SEM_UNDO;
buf1.sem_op=-1; //wait operation
semop(sem_id,&buf1,1); //wait
if(msg_id<0)
{
printf("Already exists\n");
msg_id=msgget((key_t)2341,0666);
if(msg_id<0)
{
printf("handle error\n");
return 0;
}
}
int ret=msgrcv(msg_id,&buf,sizeof(buf.mtext),30,0); //reading the MQ
if(ret<=0)
{
printf("msg sndng error\n");
}
else
{
printf("%s\n",buf.mtext);
msgctl(msg_id,IPC_RMID,NULL); //removing the MQ
semctl(sem_id,0,IPC_RMID); //removing the semaphore
}
return 0;
}
Comments