9. SP - Semaphores
9. SP - Semaphores
Semaphores
• socket
– allows processes running on different machines to
communicate with one another
communicate
Process 1 Process 2
Machine A Machine B
IPC (cont.)
• Pipes
– anonymous pipe
➢parent-child process communication
➢half duplex (i.e., data flows in only one direction)
➢can be used only between processes that have a
common ancestor
• FIFOs
– named pipe
– unrelated processes can exchange data
– It is a type of file
IPC (cont.)
• message queues
– operates in units of messages (or packets)
– a linked list of messages stored within the kernel
– identified by a message queue identifier
• shared memory
– allows two or more processes to share a given
region of memory
• semaphores
– a counter used to provide access to a shared data
object for multiple processes
Race condition
남편 잔고: 105 $ 아내
100$ 출금 70$ 출금
Race condition
• Race condition
– Situation where several processes access and
manipulate shared data concurrently
– The final value of the shared data
➢depends upon which process finishes last
do {
entry section
critical section
exit section
remainder section
} while (TRUE);
critical section
a piece of code that accesses a shared resource (data structure or device)
that must not be concurrently accessed by more than one processes.
Semaphore
• Semaphore S
– integer variable
• Two standard operations to modify S
– wait() and signal()
➢originally called P() and V()
P(S) {
while (S <= 0)
; // noop
S--;
}
If positive, decrement & enter.
Otherwise, wait until it gets positive.
V(S) {
S++;
}
Semaphore
• semflg
– If semflg specifies both IPC_CREAT and IPC_EXCL,
and a semaphore set already exists for key,
– ➔ then semget() fails with errno set to EEXIST
– is analogous to open(…, O_CREAT | O_EXCL)
semget()
• Example
– Create a semaphore set
➢key is 100
➢the number of semaphores is 1
int semid;
#include <sys/sem.h>
int semctl(int semid , int semnum , int cmd , ... /* union semun arg */);
Returns: non-negative if OK, -1 on error
• CMD
– IPC_STAT : Fetch the semid_ds structure for this set,
storing it in the structure pointed to by arg.buf
– IPC_RMID: remove the semaphore set
– SETVAL: Set the value of semval to arg.val for the
semnum-th semaphore of the set
• union semun
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
};
semctl()
• Initialize semaphore
union semun arg;
arg.val = 1;
semctl(semid, 0, SETVAL, arg);
• Remove semaphore
union semun arg;
• nops
– The number of operations in the array
semop()
• P() - wait()
• V() - signal()
vbuf.sem_num = 0;
vbuf.sem_op = 1; // adds this value to the semaphore value(semval).
vbuf.sem_flg = SEM_UNDO;
• Example
#include <sys/ipc.h>
#include <sys/sem.h>
…
pbuf.sem_num = 0;
pbuf.sem_op = -1;
pbuf.sem_flg = SEM_UNDO;
• Example (cont.)
vbuf.sem_num = 0;
vbuf.sem_op = 1;
vbuf.sem_flg = SEM_UNDO;
• Example (cont.)
• Example (cont.)
void handlesem(key_t skey)
{
int semid, pid = getpid();
• Example (cont.)
if(fork() == 0)
handlesem(semkey);
if(fork() == 0)
handlesem(semkey);
if(fork() == 0)
handlesem(semkey);
}
Semaphore example
• Results
kwangwoon@kw-server:~/test/semaphore$ ./a.out
process 19496 before critical section
process 19496 is in critical section
process 19498 before critical section
process 19497 before critical section
kwangwoon@kw-server:~/test/semaphore$
(after 5 seconds)
process 19496 is leaving critical section
process 19496 is exiting
process 19498 is in critical section
(after 5 seconds)
process 19498 is leaving critical section
process 19498 is exiting
process 19497 is in critical section
(after 5 seconds)
process 19497 is leaving critical section
process 19497 is exiting
POSIX semaphore
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);
Returns: the address of the new semaphore if OK, SEM_FAILED on error
#include <semaphore.h>
• lock a semaphore
• sem_wait()
– decrements (locks) the semaphore pointed to by
sem
– If the semaphore's value is greater than zero, then
it decrements, and the function returns
– If the value is zero, then the call blocks until it
becomes positive
sem_wait()
• sem_trywait()
– same as sem_wait(), except that if the decrement
cannot be immediately performed, then call returns
an error instead of blocking
• sem_timedwait()
– same as sem_wait(), except that abs_timeout
specifies a limit on the amount of time that the call
should block if the decrement cannot be
immediately performed
➢struct timespec {
➢ time_t tv_sec; /* seconds */
➢ long tv_nsec; /* nanoseconds */
➢};
sem_post()
#include <semaphore.h>
• unlock a semaphore
– increments (unlocks) the semaphore pointed to by
sem
– If the semaphore's value consequently becomes
greater than zero, then another process blocked in
a sem_wait call will be woken up and proceed to
lock the semaphore
sem_unlink()
#include <semaphore.h>
• Example
/* 생략 */
sem_t *mysem;
if((mysem = sem_open("mysem", O_CREAT, 0777, 1)) == NULL) {
perror("Sem Open Error");
return 1;
}
while(1) {
sem_wait(mysem);
fd = open(countFile,O_RDWR);
lseek(fd, 0, SEEK_SET);
read(fd, (void *)&count, sizeof(count));
printf("Read Data %d\n",count);
count++;
critical section
lseek(fd, 0, SEEK_SET);
write(fd, (void *)&count, sizeof(count));
sleep(1);
close(fd);
sem_post(mysem);
}