8/8/2019 Lec 20 Semaphores
1/22
Lecture 20
Semaphores
Lecture 20
SemaphoresTopicsTopics System V IPC: Semaphores
Semaphore Sets
November 1, 2005
CSCE 510 Systems Programming
8/8/2019 Lec 20 Semaphores
2/22
8/8/2019 Lec 20 Semaphores
3/22
3 CSCE 510 Fall 2005
System V IPC - reviewSystem V IPC - review
System V IPCSystem V IPC
ObjectsObjects
Shared memory segments two program shared a piece of memory
Msgqueues - a priority queue for messages, guaranteed atomic
Semaphore sets Sets of semaphores as in CSCE 311
Each semaphore can control access to another IPC object say shared memory
segment
Different from I/O systemDifferent from I/O system special functions for creating, reading,special functions for creating, reading,and writingand writing
8/8/2019 Lec 20 Semaphores
4/22
4 CSCE 510 Fall 2005
MSG_Queues Overview of FunctionsMSG_Queues Overview of Functions
key_t ftok(const char *pathname, int proj_id);key_t ftok(const char *pathname, int proj_id);
int msgget(key_t key, int msgflg);int msgget(key_t key, int msgflg);
Flags perms | IPC_CREAT | IPC_EXCL // to create a new one
int msgctl(int msqid, int cmd, struct msqid_ds *buf);int msgctl(int msqid, int cmd, struct msqid_ds *buf);
int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, longssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, longmsgmsg--typ, int msgflg);typ, int msgflg);
8/8/2019 Lec 20 Semaphores
5/22
5 CSCE 510 Fall 2005
SemaphoresSemaphores
E. W. DijkstraE. W. Dijkstra
P(sem) or wait(sem)P(sem) or wait(sem)
if( sem != 0)if( sem != 0)
decrement sem by onedecrement sem by one
elseelse
wait until sem becomes nonwait until sem becomes non--zero, then decrementzero, then decrement
V(sem) or Signal(sem)V(sem) or Signal(sem)increment sem by oneincrement sem by one
if( queue of waiting processes is not empty)if( queue of waiting processes is not empty)
restart first process in the wait queuerestart first process in the wait queue
8/8/2019 Lec 20 Semaphores
6/22
6 CSCE 510 Fall 2005
Semaphore InvariantSemaphore Invariant
The Semaphore Invariant below is always true!The Semaphore Invariant below is always true!
(semaphores initial value(semaphores initial value
+ number of signal operations+ number of signal operations
-- number of completed wait operations) >= 0number of completed wait operations) >= 0
Semaphores can be used for mutual exclusion.Semaphores can be used for mutual exclusion.
8/8/2019 Lec 20 Semaphores
7/22
7 CSCE 510 Fall 2005
Semaphore SetsSemaphore Sets
FunctionsFunctions
int semget(key_t key, int nsems, int semflg);int semget(key_t key, int nsems, int semflg);
int semctl(int semid, int semnum, int cmd, ...);int semctl(int semid, int semnum, int cmd, ...);
int semop(int semid, struct sembuf *sops, unsigned nsops);int semop(int semid, struct sembuf *sops, unsigned nsops);
8/8/2019 Lec 20 Semaphores
8/22
8 CSCE 510 Fall 2005
Values associated with SemaphoresValues associated with Semaphores
Associated with each semaphore in the set are the values:Associated with each semaphore in the set are the values:
SemvalSemval the semaphore value always >= 0the semaphore value always >= 0
SempidSempid process id of last process to act on semaphoreprocess id of last process to act on semaphore
SemcntSemcnt number of process waiting for sem to get larger valuenumber of process waiting for sem to get larger value SemzcntSemzcnt number of process waiting for semaphore to be zeronumber of process waiting for semaphore to be zero
8/8/2019 Lec 20 Semaphores
9/22
9 CSCE 510 Fall 2005
int semget();int semget();
int semget(key_t key, int nsems, int semflg);int semget(key_t key, int nsems, int semflg);
key_t keykey_t key
int nsemsint nsems number of semaphores to be in the setnumber of semaphores to be in the set
int semflgint semflg IPC_CREAT and IPC_EXCL
8/8/2019 Lec 20 Semaphores
10/22
10 CSCE 510 Fall 2005
int semctl(); - Semaphore Controlint semctl(); - Semaphore Control
int semctl(int semid, int semnum, int cmd, ...);int semctl(int semid, int semnum, int cmd, ...);
int semidint semid
int semnumint semnum
int cmdint cmd
IPC_STAT stat semaphore data into structure pointed to by arg.buf IPC_SET copy data to semid_ds structure pointed to by arg.buf
IPC_RMID - Immediately remove the semaphore set and its data structures awakening
all waiting processes
More commands on next sldie
... Optional fourth argument arg of type semun on upcoming slide... Optional fourth argument arg of type semun on upcoming slide
8/8/2019 Lec 20 Semaphores
11/22
11 CSCE 510 Fall 2005
More Semctl CommandsMore Semctl Commands
GETALLGETALL -- Return semval for all semaphores of the set intoReturn semval for all semaphores of the set intoarg.arrayarg.array
GETNCNTGETNCNT -- returns the value of semncnt for the semnumreturns the value of semncnt for the semnum--ththsemaphore of the setsemaphore of the set
GETPIDGETPID
GETVALGETVAL -- returns the value of semval for the semnumreturns the value of semval for the semnum--ththsemaphore of the setsemaphore of the set
GETZCNTGETZCNT -- returns the value of semzcntreturns the value of semzcnt
SETALLSETALL
SETVALSETVAL
8/8/2019 Lec 20 Semaphores
12/22
12 CSCE 510 Fall 2005
Semctl Return ValuesSemctl Return Values
Return values from semctlReturn values from semctl
GETNCNT the value of semncnt.GETNCNT the value of semncnt.
GETPID the value of sempid.GETPID the value of sempid.
GETVAL the value of semval.GETVAL the value of semval. GETZCNT the value of semzcnt.GETZCNT the value of semzcnt.
All other cmd values return 0 on success.All other cmd values return 0 on success.
--1 on error and set global value errno1 on error and set global value errno
8/8/2019 Lec 20 Semaphores
13/22
13 CSCE 510 Fall 2005
Semun Data StructureSemun Data Structure
union semun {union semun {
int val;int val; /* value for SETVAL *//* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* array for GETALL, SETALL */unsigned short *array; /* array for GETALL, SETALL */
/* Linux specific part: *//* Linux specific part: */
struct seminfo *__buf; /* buffer for IPC_INFO */struct seminfo *__buf; /* buffer for IPC_INFO */
};};
8/8/2019 Lec 20 Semaphores
14/22
14 CSCE 510 Fall 2005
/* Structure used for argument to `semop' to describe operations. *//* Structure used for argument to `semop' to describe operations. */
struct sembufstruct sembuf
{{
unsigned short int sem_num; /* semaphore number */unsigned short int sem_num; /* semaphore number */short int sem_op; /* semaphore operation */short int sem_op; /* semaphore operation */
short int sem_flg; /* operation flag */short int sem_flg; /* operation flag */
};};
8/8/2019 Lec 20 Semaphores
15/22
15 CSCE 510 Fall 2005
Semop() Semaphore OperationsSemop() Semaphore Operations
int semop(int semid, struct sembuf *sops, unsigned nsops);int semop(int semid, struct sembuf *sops, unsigned nsops);
A semaphore is represented by an anonymous structure including theA semaphore is represented by an anonymous structure including thefollowing members:following members:
unsigned short semval; /* semaphore value */unsigned short semval; /* semaphore value */
unsigned short semzcnt; /* # waiting for zero */unsigned short semzcnt; /* # waiting for zero */
unsigned short semncnt; /* # waiting for increase */unsigned short semncnt; /* # waiting for increase */
pid_t sempid; /* process that did last op */pid_t sempid; /* process that did last op */
8/8/2019 Lec 20 Semaphores
16/22
16 CSCE 510 Fall 2005
SemHeader.hSemHeader.h
#include #include #include #include
#include #include
#include #include
#define SEMPERM 0600#define SEMPERM 0600
typedef union {typedef union {
int val;int val;struct semid_ds *buf;struct semid_ds *buf;
ushort *array;ushort *array;
} semun;} semun;
8/8/2019 Lec 20 Semaphores
17/22
17 CSCE 510 Fall 2005
InitSemInitSem
int initsem( key_t semkey)int initsem( key_t semkey){{
int status = 0;int status = 0;
int semid;int semid;
if((semid = semget(semkey, 1, SEMPERM | IPC_CREAT| IPC_EXCL)) ==if((semid = semget(semkey, 1, SEMPERM | IPC_CREAT| IPC_EXCL)) == --1)1)
{{
if(errno == EEXIST)if(errno == EEXIST)
semid = semget(semkey, 1, 0);semid = semget(semkey, 1, 0);
} else {} else {
semun arg;semun arg;arg.val = 1;arg.val = 1;
status = semctl (semid,0, SETVAL, arg);status = semctl (semid,0, SETVAL, arg);
}}
8/8/2019 Lec 20 Semaphores
18/22
18 CSCE 510 Fall 2005
if(semid ==if(semid == --1 || status ==1 || status == --1)1)
{{
perror("initsem failed");perror("initsem failed");
return(return(--1);1);}}
return(semid);return(semid);
}}
8/8/2019 Lec 20 Semaphores
19/22
19 CSCE 510 Fall 2005
Simple Wait wait function |set| =1Simple Wait wait function |set| =1
int wait(int semid)int wait(int semid)
{{
struct sembuf p_buf;struct sembuf p_buf;
p_buf.sen_num = 0;p_buf.sen_num = 0;p_buf.semop =p_buf.semop = --1;1; /* normal decrement by one *//* normal decrement by one */
p_buf.sem_flg = SEM_UNDO;p_buf.sem_flg = SEM_UNDO;
if(semop(semid, &p_buf,1) ==if(semop(semid, &p_buf,1) == --1)1)
err_quit(wait operation failed);err_quit(wait operation failed);
return(0);return(0);
}}
8/8/2019 Lec 20 Semaphores
20/22
20 CSCE 510 Fall 2005
Simple Signal signal function |set| =1Simple Signal signal function |set| =1int signal(int semid)int signal(int semid)
{{
struct sembuf v_buf;struct sembuf v_buf;
v_buf.sem_num = 0;v_buf.sem_num = 0;
v_buf.semop = 1;v_buf.semop = 1;
v_buf.sem_flg = SEM_UNDO;v_buf.sem_flg = SEM_UNDO;
if(semop(semid, &v_buf, 1) ==if(semop(semid, &v_buf, 1) == --1)1)
err_quit(wait operation failed);err_quit(wait operation failed);return(0);return(0);
}}
8/8/2019 Lec 20 Semaphores
21/22
21 CSCE 510 Fall 2005
testsemtestsem
Void handlesem(key_t skey);Void handlesem(key_t skey);
Main(){Main(){
int i;int i;
key_t semkey = 0x200;key_t semkey = 0x200;for(i=0; I < 3; ++i){for(i=0; I < 3; ++i){
if(fork() == 0)if(fork() == 0)
handlesem(semkey);handlesem(semkey);
}}
}}
8/8/2019 Lec 20 Semaphores
22/22
22 CSCE 510 Fall 2005
void handlesem(key_t skey){void handlesem(key_t skey){
int semid;int semid;
pid_t pid = getpid();pid_t pid = getpid();
if((semid = initsem(skey)) < 0) exit(1);if((semid = initsem(skey)) < 0) exit(1);
printf(printf(\\npid %d before entering critical sectionnpid %d before entering critical section\\n, pid);n, pid);
wait(semid);wait(semid);
printf(printf(\\npid %d in critical sectionnpid %d in critical section\\n, pid);n, pid);
sleep(10);sleep(10);
printf(printf(\\npid %d leaving critical sectionnpid %d leaving critical section\\n, pid);n, pid);
signal(semid);signal(semid);
}}