Pipe, Signal, and Semaphore (revised)

advertisement
Nov. 3, 2015
Kyu Ho Park
Lecture 8
Pipe,
Signal,
Semaphore
(Homework #3 included)
Schedule of
Lectures, Projects and Homeworks
Lecture 9
HW#3
Lecture 10
HW#3 Due
Lecture 11
Project 4
Lecture 12
HW#4
Project 3
Due Day
Schedule of
Lectures, Projects and Homeworks
Lecture 13
Project 4
Due Day
Project 5
HW#4 Due
Day
Tutorial
for Project5
final exam. week
Project 5
Due Day
IPC in Linux
 Pipe(FIFO File)
 Signal
 Semaphore
 Shared memory
 Message queues
$command1 | command2
Standard
output
Keyboard
pipe
command 1
Standard
input
command 2
screen
Pipe
#include <unistd.h>
int pipe(int filedes[2]);
- filedes: file descriptors, filedes[0] for reading , filedes[1] for
writing.
- return value: 0 when successful, -1 when failed.
Characteristics of PIPE
 If the pipe is empty, the reading process is blocked to sleep.
 If there is a blocked process for read, writing to the pipe
wakes up the reader process.
 Therefore pipe has two functions, ( ?) and ( ?).
pipe
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
close(fd_in);
close(fd[1]);
exit(0);
}
void error_exit(char * message);
else {
close(fd[1]);
fd_out = creat("output",0666);
if(fd_out ==-1)
error_exit("creat");
int main(void)
{
int fd[2];
int fd_in, fd_out;
int n;
char buf[10]="message";
while((n=read(fd[0], buf, 10)) !=0)
write(fd_out, buf,n);
close(fd_out);
close(fd[0]);
wait();
if( pipe(fd) == -1)
exit(1);
}
if( fork()==0)
{
fd_in=open("input",0);
if(fd_in ==-1)
exit(1);
close(fd[0]);
while( (n=read(fd_in,buf, 10)) !=0)
write(fd[1], buf, n);
return 0;
}
void error_exit(char *message)
{
fprintf(stderr, "%s\n", message);
exit(-1);
}
root@ubuntu:~/Test/FIFO# ./pipecopy < input >output
root@ubuntu:~/Test/FIFO# more output
HelloAgain!
fd[1]
input
buf
Child process
fd[0]
Pipe
buf
Parent process
output
Named Pipe: FIFO
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
- pathname: FIFO path name,
- mode: FIFO file access permission,
- return value: 0 if successul, -1 if failed.
FIFO is a special file and its function is nearly the same as the pipe. The
pipe is a communication channel without any name but FIFO is
registered special file by mkfifo systemcall.
FIFO example
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
int main()
{
int res = mkfifo(“/home/kpark/my_fifo”, 0777);
if( res ==0) printf( “FIFO is created\n”);
exit(1);
}
Read and write using FIFO
read_fifo.c
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#define MSGSIZE 64
main()
{
char msg[MSGSIZE];
int filedes;
int nread, cnt;
if(mkfifo("./fifo", 0666) == -1)
{
printf("fail to call fifo()\n");
exit(1);
}
if((filedes = open("./fifo", O_RDWR)) < 0)
{
printf("fail to call fifo()\n");
exit(1);
}
for(cnt = 0; cnt < 3; cnt++)
{
if((nread = read(filedes, msg, MSGSIZE)) < 0)
{
printf("fail to call read()\n");
exit(1);
}
printf("recv: %s\n", msg);
}
unlink("./fifo");
}
write_fifo.c
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#define MSGSIZE 64
main()
{
char msg[MSGSIZE];
int filedes;
int cnt;
if((filedes = open("./fifo", O_WRONLY)) < 0)
{
printf("fail to call open()\n");
exit(1);
}
for(cnt = 0; cnt < 3; cnt++)
{
printf("input a message: ");
scanf("%s", msg);
if(write(filedes, msg, MSGSIZE) == -1)
{
printf("fail to call write()\n");
exit(1);
}
sleep(1);
}
}
Embedded Software
2015. 9.1
Kyu Ho Park
CORE Lab.
Signals
SIGNALS
14
signals
 Signals are software interrupt and provide a
basic method of interprocess communication.
 The generation of a signal is occurred by some
error conditions(memory segment violations,
floating-point processor errors) and illegal
instructions.
15
Signal sending
 Two functions for raising signals:
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
int raise(int sig);
 kill( ) can send any signal to any process group or
process.
 raise() is used for a process to send a signal to itself.
It is equivalent to kill(getpid(), sig).
16
kill() process selection
 When
17
pid > 0 :signal sent to process with proc_id = pid.
pid = 0 :sent to all processes whose process group
id is the same as the sender for whom the
sender has permission.
pid < -1 : sent to all processes whose process group
id is the absoluter value of pid and for
whom the sender has permission.
pid = -1: sent to every process except for the first
one , from higher numbers in the
process table to lower.
18
Alarm, pause and sleep
 #include <unistd.h>
unsigned int alarm(unsigned int seconds);
/*After the expiration of an assigned time, it
sends SIGALARM to itself */
 #include <unistd.h>
int pause(void);
/*pause until a signal received, return value is
always -1 */
unsigned int sleep(unsigned int seconds);
19
sigPause.c
20
Signal handler
 #include <signal.h>
(void) signal(SIGINT, handler );
The signal handler is set to handler() which may
be a user specified function or one of {SIG_IGN,
SIG_DFL}.
21
22
Typical Signal Handling
1.
2.
3.
4.
5.
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void handler(int sig)
{ printf(“I received a signal %d\n”, sig);}
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
int main()
{ struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_handler=handler;
sigaction(SIGINT,&act,0);
while(1) {
printf(“Hello EE516!\n”);
sleep(1);
}
}
23
struct sigaction{
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
}
sigfillset(),sigemptyset()
,sigaddset(), sigdelset(),and sigismember()
#include <signal.h>
int sigfillset(sigset_t *set); //fill the set with all signals.
int sigemptyset(sigset_t *set); //empty the set.
int sigaddset(sigset_t *set, int signum);//signum is the signal number
sigaction( )
#include <signal.h>
int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
/*
act: action to do for the signal .
oldact: previously determined action for the signal, normally set to
*/
struct sigaction{
void (*sa_handler)(int);//function, SIG_DFL, or SIG_IGN
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask; //signals to block in sa_handler
int sa_flags; //signal action modifiers
}
NULL.
sigprocmask( )
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
/*
how={SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK}
*/
Semaphore
Synchronization with semaphores
Two set of functions for sepaphore:
- POSIX semaphore functions for threads,
- System V semaphore functions for processes.
POSIX semaphore
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
- sem: points to a semaphore object, pshared: if 0, the semaphore is local to the
current process, else the semaphore may be shared between processes(Linux does
not support it). value: initial value of the semaphore.
int sem_wait(sem_t *sem);
-This function waits until the semaphore is nonzero, and decreases the value of
semaphore by 1.
int sem_post(sem_t *sem);
-This function increases the value of the semaphore by 1.
int sem_destroy(sem_t *sem);
30
System V semaphore
Semaphore Definition:
P(sem) : If sem is greater than 0, decrement sem,
If sem is zero, suspend execution of this process.
V(sem) : If some other process has been suspended waiting
for sem, make it resume execution. If no process is
suspended waiting for sem, increment sem.
// sem = semmaphore variable.
semget( )
#include <sys/sem.h>
int semget(key_t key, int num_sems, int sem_flags);
key: an integer value used to allow unrelated processes to access
the same semaphore. The key is used only with semget. All other
semaphore functions use the semaphore identifier(sem_id)
returned from semget.
num_sems: the number of semaphores.
sem_flags: IPC_CREAT | IPC_EXCL
return value: positive integer which is the semaphore identifier, -1 on
error.
semop()
int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops);
This function is used for changing the value of the semaphore.
sem_id: the value returned from semget.
sem_ops: a pointer to an array of structure sembuf as below
struct sembuf {
short sem_num; // 0 usually
short sem_op; // -1 for P operation, +1 for V
// operation.
short sem_flg; //usually SEM_UNDO
}
semctl( )
int semctl(int sem_id, int sem_num, int command, ..);
This function allows direct control of semaphore information.
command: To remove the semaphore set, cmd should be set to
IPC_RMID. In this case sem_num and arg have no meaning.
To initialize a semaphore to a known value, cmd should be set to
SETVAL.
semctl(semid, 0, IPC_RMID, dummy);
set_semaphore example
/* The function set_semvalue initializes the semaphore using the SETVAL
command in a
semctl call. We need to do this before we can use the semaphore. */
static int set_semvalue(void)
{
union semun sem_union;
sem_union.val = 1;
if (semctl(sem_id, 0, SETVAL, sem_union) == -1) return(0);
return(1);
}
del_semaphre example
/* The del_semvalue function has almost the same form, except the call to semctl uses
the command IPC_RMID to remove the semaphore's ID. */
static void del_semvalue(void)
{
union semun sem_union;
if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
fprintf(stderr, "Failed to delete semaphore\n");
}
semaphore_p example
/* semaphore_p changes the semaphore by -1 (waiting). */
static int semaphore_p(void)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1; /* P() */
sem_b.sem_flg = SEM_UNDO;
if (semop(sem_id, &sem_b, 1) == -1) {
fprintf(stderr, "semaphore_p failed\n");
return(0);
}
return(1);
}
semaphore_v example
/* semaphore_v is similar except for setting the sem_op part of the sembuf structure to 1,
so that the semaphore becomes available. */
static int semaphore_v(void)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1; /* V() */
sem_b.sem_flg = SEM_UNDO;
if (semop(sem_id, &sem_b, 1) == -1) {
fprintf(stderr, "semaphore_v failed\n");
return(0);
}
return(1);
}
semun.h
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
/* union semun is defined by including <sys/sem.h> */
#else
/* according to X/OPEN we have to define it ourselves */
union semun {
int val;
/* value for SETVAL */
struct semid_ds *buf;
/* buffer for IPC_STAT, IPC_SET */
unsigned short int *array; /* array for GETALL, SETALL */
struct seminfo *__buf;
/* buffer for IPC_INFO */
};
#endif
Homework #3
 At the last part of the printed handout ‘System V
IPC(Semaphore), there are three sample programs seminit.c,
semdemo.c, and semrm.c.
 Task 1: analyze those three programs and explain the
behavior of each program and their expected output of
each programs.
 Task 2: make run those programs suggested at the section
‘Sample programs’ and show each output of those programs.
 Due: Nov.10, 23:59. Other guidelines are the same as the
previous homeworks.
 Submit it to Joo Kyung Ro, eu8198@kaist.ac.kr)
Supplement to IPC:
41
Interprocess Communication
 Processes:
Independent Processes or Cooperating Processes
 IPC issues:
1. How one process can pass information to another.
2. Mutual Exclusion.
3. Proper sequencing when dependencies are present.
42
42
Interprocess Communication(IPC)
Message Passing
process A
Shared Memory
M
process A
1
process B
shared
M
process B
2
kernel
M
1
kernel
2
Producer-Consumer Problem
 Paradigm for cooperating processes,
producer process produces
information that is consumed by a
consumer process
unbounded-buffer places no practical
limit on the size of the buffer
bounded-buffer assumes that there is a
fixed buffer size
44
Message Passing (1)
 Figure 2-17. The producer-consumer problem
with N messages.
...
...
Message Passing (2)
 Figure 2-17. The producer-consumer problem
with N messages.
Message Passing
 Message system – processes communicate with each other without
resorting to shared variables
 Message passing facility provides two operations:
 send(message) – message size fixed or variable
 receive(message)
 If P and Q wish to communicate, they need to:
 establish a communication link between them
 exchange messages via send/receive
 Implementation of communication link
 physical (e.g., shared memory, hardware bus)
 logical (e.g., logical properties)
Implementation Questions
 How are links established?
 Can a link be associated with more than two
processes?
 How many links can there be between every
pair of communicating processes?
 What is the capacity of a link?
 Is the size of a message that the link can
accommodate fixed or variable?
 Is a link unidirectional or bi-directional?
Direct Communication
 Processes must name each other explicitly:
 send (P, message) – send a message to process P
 receive(Q, message) – receive a message from process Q
 Properties of communication link
 Links are established automatically
 A link is associated with exactly one pair of communicating
processes
 Between each pair there exists exactly one link
 The link may be unidirectional, but is usually bi-directional
Indirect Communication
 Messages are directed and received from mailboxes (also
referred to as ports)
 Each mailbox has a unique id
 Processes can communicate only if they share a mailbox
 Properties of communication link
 Link established only if processes share a common mailbox
 A link may be associated with many processes
 Each pair of processes may share several communication
links
 Link may be unidirectional or bi-directional
Indirect Communication
 Operations
 create a new mailbox
 send and receive messages through mailbox
 destroy a mailbox
 Primitives are defined as:
send(A, message) – send a message to mailbox A
receive(A, message) – receive a message from
mailbox A
Indirect Communication
 Mailbox sharing
 P1, P2, and P3 share mailbox A
 P1, sends; P2 and P3 receive
 Who gets the message?
 Solutions
 Allow a link to be associated with at most two processes
 Allow only one process at a time to execute a receive
operation
 Allow the system to select arbitrarily the receiver. Sender is
notified who the receiver was.
Synchronization
 Message passing may be either blocking or non-blocking
 Blocking is considered synchronous
 Blocking send has the sender block until the message is
received
 Blocking receive has the receiver block until a message is
available
 Non-blocking is considered asynchronous
 Non-blocking send has the sender send the message and
continue
 Non-blocking receive has the receiver receive a valid
message or null
Buffering
 Queue of messages attached to the link;
implemented in one of three ways
1.Zero capacity – 0 messages
Sender must wait for receiver (rendezvous)
2.Bounded capacity – finite length of n messages
Sender must wait if link full
3.Unbounded capacity – infinite length
Sender never waits
Bounded-Buffer – Message Passing Solution
The Producer
Channel mailBox;
while (true) {
Date message = new Date();
mailBox.send(message);
}
Bounded-Buffer – Message Passing Solution
The Consumer
Channel mainBox;
while (true) {
Date message = (Date) mailBox.receive();
if(message != NULL)
/*consume the message */
}
Monitors
 A high-level abstraction that provides a
convenient and effective mechanism for
process synchronization
 Only one process may be active within
the monitor at a time
Schematic view of a Monitor
Fence
P1
P2
Entry E
Entry F
P4
Entry G
P5
Condition C
Critical
Data
Condition D
Waiting
Signalers
P3
P6
Condition Variables
 Condition c, d;
 Two operations on a condition
variable:
c.wait () – a process that invokes the
operation is suspended.
c.signal () – resumes one of processes
(if any) that invoked c.wait ()
Monitor with Condition Variables
Fence
P1
P2
Entry E
Entry F
P4
Entry G
P5
Condition C
Critical
Data
Condition D
Waiting
Signalers
P3
P6
Monitor with Condition Variables
Fence
P1
P2
Condition C
Entry E
Critical
Data
Entry F
Condition D
Waiting
Signalers
P4
Entry G
P3
P6
P5
Monitors (1)
Monitors (2)
Monitors (3)
Download