Top Banner
TDC368 UNIX and Network Programming Camelia Zlatea, PhD Email: czlatea @ cs . depaul . edu Week 5-6: Named Pipe Asynchronous Events UNIX Signals
39

TDC368 UNIX and Network Programming

Jan 02, 2016

Download

Documents

Tamara Price

TDC368 UNIX and Network Programming. Week 5-6: Named Pipe Asynchronous Events UNIX Signals. Camelia Zlatea, PhD Email: [email protected]. Overview Pipe Inter Process Communication (IPC ). Pipes internally are called FIFO files can be read or written only sequentially - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: TDC368 UNIX and Network Programming

TDC368UNIX and Network Programming

Camelia Zlatea, PhD

Email: [email protected]

Week 5-6: Named Pipe Asynchronous Events UNIX Signals

Page 2: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 2Spring 2003

Overview Pipe Inter Process Communication (IPC )

Pipes 1. internally are called FIFO files 2. can be read or written only sequentially 3. comparing with regular files FIFO files (or pipes) use only directly addressable

blocks (for this reason there is a limit for the maximum size of the pipe PIPE_BUF (defined in <limits.h>)

4. at a given time only one process can access a FIFO file for reading or writing

Operations On Pipes:1. open, read, write, close2. a read operation always succeeds on pipe (FIFO file).

If the pipe is empty then the process sleeps until the pipe is written by another process. Otherwise the read function will return the actual number of bytes read.

3. a write operation on pipe will succeed if there is enough space to write into the FIFO file. Otherwise, the process that called write will sleep until the pipe is read from by another process, thus more space is created

4. if there are processes sleeping on read request and the last writer process closes the pipe, then the sleeping processes are wake-up and return 0 bytes.

5. if there are processes sleeping on write request and the last reader process closes the pipe, then the sleeping processes are sent an error signal.

Page 3: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 3Spring 2003

Unamed Pipe ( see also TDC368_week3_4.ppt)

A template to implement communication via unnamed pipes:

– 1.      create the pipe(s) necessaries

– 2.      generate the child process(es)

– 3.      close/duplicate file descriptors to associate correctly the ends of the

– pipe

– 4.      close the unneeded file descriptors (ends of the pipe)

– 5.      execute necessaries operations

– 6.      close the remaining file descriptors for more accuracy, wait for child

– process to terminate

Page 4: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 4Spring 2003

Named Pipes Concept:

1. special file of type FIFO2. an inod is associated with the named pipe3. named pipe has a directory entry4. difference between ordinary files and named pipes is in how read and write

operations are synchronized when accessing the file. Kernel ensures that a read does not wait on an empty pipe, nor a write wait on a full pipe. In these cases the processes will sleep, and they will be wake-up when the required event take place.

5. can be shared by unrelated processes Create a named pipe at the shell level

mknod file_pipe p - argument file_pipe is the name of the pipe- argument “p” notifies mknod to create a named pipe- file type for “file_pipe” is “p” (see ls -l file_pipe)

mkfifo –p file_pipe ( use this on hawk ) Example:

mkfifo –p PIPE ls - l > PIPE &cat < PIPE

Page 5: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 5Spring 2003

Named Pipes

System call to generate a named pipe - mknod#include <sys/types.h>

#include <sys/stat.h>

int mknod(const char *path, mode_t, 0); /* for non-privileged users */

UNIX I/O function - mkfifo#include <sys/types.h>

#include <sys/stat.h>

int mkfifo(const char *path, mode_t mode);

Page 6: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 6Spring 2003

Asynchronous Events

Examples of process events:– a signal from another process– an interrupt from a device– completion of a I/O request

Signals are events delivered to a process via UNIX. The process has no control over when they arrive. Signals are understood as software version of hardware interrupts.

Signals can be generated by:– hardware: ex: division by zero, illegal address access– kernel: ex: completion of a I/O request issued by the waiting

process– user processes: ex: communication among processes related to

relevant events, child termination notified to parent– user actions: ex: pressing the keyboard sequence for: quit,

interrupt To find the current mapping of the key sequences for

various signals, call shell command: stty -a– Example: SIGINT is mapped to "ctrl + c" (or DEL)

Page 7: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 7Spring 2003

Some important signals

Signal SigNr Default Meaning SIGALARM 14 EXit Setting an allarm clock

SIGCHLD 18 Ignore Child status changed

SIGFPF 8 Exit,core Arithmetic exception

SIGHUP 1 Exit Hangup

SIGINT 2 Exit Interrupt

SIGKILL 9 Exit Killed

SIGQUIT 3 Exit,core Quit

SIGSTOP 23 Stop Stopped (signal)

SIGTERM 15 Exit Terminated

SIGUSR1 16 Exit User signal 1

SIGUSR2 17 Exit User signal 2

Page 8: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 8Spring 2003

Systems Calls/Commands (Common UNIX signals (pp.266-270 textbook Stevens)

kill system call– sends a signal to a process

#include <sys/types.h> #include <signal.h> int kill(pid_t pid, int signo);

the argument pid determines how the signal is handled and to which process it applies.– if pid > 0 then the signal applies to process with ID = pid– if pid = 0 then the signal applies to all processes from the Process Group– if pid = -1 then the signal applies to all processes with UID = EUID of sender– UNIX exploits the power of the superuser in a clever manner. For example to execute command “df”

(display disk free blocks) the process need to red bloc 0, where this information resides. Superuser is able to read bloc 0, but not a non-privileged user. In this case executable “df” has setuid bit set on. This bit is part of the protectiin mode word, whose protection part uses only 9bits (the other being left for other purposes). Thus, when a user calls “df” , the effective EUID of process “df” becomes equal with UID of the superuser.

– if pid < -1 then the signal applies to all processes in the process group with GID = |pid| ; the argument signo - the signal number.

kill command: %kill [-signal] pid1 pid2 ….– kill -l list all signals known by kill

Page 9: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 9Spring 2003

More about kill

kill –0 pid --- test to see of process pid is still in the system

kill(pid, 0); --- test to see of process pid is still in the system

Page 10: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 10Spring 2003

Unix System Calls to handle signals

Signal system call is used to install signal handlers./* legacy UNIX API */

#include <signal.h> void (*signal(int signo, void (*handler)(int)))(int);

#include <signal.h>

void (*sigset (int sig_no, void (*handler)(int)))(int);

– The second parameter of the signal system call is a pointer to a

function that returns void and takes a single integer as its argument, and the return value of signal itself is a pointer to a function that returns void and takes a single integer argument.

– The second parameter to signal is a pointer to the function to call whenever the signal is delivered.

– The return value is the previous signal handler that was installed before the new one was added.

Page 11: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 11Spring 2003

Calling prototype for signal() and sigset()

signal() and sigset() take two arguments, an integer sig and a pointer to a function, catcher() that returns nothing, to be called when sig occurs

if invocation of signal() is successful it returns a pointer to the previous disposition of catcher() function

if invocation of sigset() is successful and sig is not blocked it returns a pointer to the previous disposition of catcher()

if invocation of sigset() is successful and sig is blocked it returns SIG HOLD

(int) at the end of prototype indicate that catcher() takes an integer (sig number) as argument

Page 12: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 12Spring 2003

Signal management

– A process can associate a signal catching function with every signal by either signal() or sigset() system calls

– Upon the receipt of a signal for which a catcher() is installed the system calls catcher() to process the signal

– the catcher() must be reinstalled in order to catch other signals; however, race conditions may occur in this way

» ONLY when using signal() system call

Page 13: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 13Spring 2003

Signal Acceptance

Signals can be generated by outside events. When a process receives a signal then the following actions can be

taken:1. ignore the signal

2. terminate the process (the default action SIG_DFL)

3. process the signal - take a particular action

Page 14: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 14Spring 2003

Signal Acceptance

1. Ignore the signalProgram that ignores control-C. When an INT signal (control-C) isReceived, the process ignores it (SIG_IGN is the handler)

#include <stdio.h> #include <sys/types.h> #include <signal.h>

int main (void) { signal (SIGINT, SIG_IGN); while(1) {

printf("Hello\n");

} }

Page 15: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 15Spring 2003

Signal Acceptance

2. Terminate the process (the default action SIG_DFL)Default action (see manual pages man signal) is the action executed if

nothing else

#include <iostream.h>

#include <signal.h>

int main()

{

signal(SIGINT, SIG_DFL); /* catch signal SIGINT=2 */

pause();

/* wait for a signal interruption */

}

Page 16: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 16Spring 2003

Terminate the process (the default action SIG_DFL)

Default action (see manual pages man signal) is the action executed if nothing else is specified related to a particular signal:

exit - executes all actions associated with exit system call#include <unistd.h>

void _exit(int status);– When terminating a process the following actions are performed:

1. all open file descriptors are closed2. child notifies termination to his parent by signaling SIGCHLD3. if parent is waiting for the child to terminate, then status information is

returned to it.4. all children of the terminating process will have their PPID set to 1 (init

process adopts them)5. if terminating process is a group leader, then al the group members will be

sent SIGHUP or SIGCONT signals core - generate a file - core image and then exit stop - suspend the execution of the process (SIGSTOP cannot

be caught or ignored) ignore - the signal has no effect on the process

Page 17: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 17Spring 2003

Signal Acceptance

3. Handle the signal - Take a particular action» The target process executes the action associated with the signal. » Processing the signal depends also on the state of the process and level of priority.

Signals can be caught by specifying a signal catching routine. » The signals SIGKILL and SIGSTOP are never caught and they always terminate a

process.

#include <stdio.h> #include <sys/types.h> #include <signal.h>

void action (int sig){

signal (SIGINT, action);

printf ("control-C won't stop this process!\n");

}

int main (void){

signal (SIGINT, action);

while(1) {

printf("Hello\n");

}

}

Page 18: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 18Spring 2003

Handle the signal - Take a particular action (con’t)

The action taken when a signal is generated depends on:         signal handler         process signal mask

» Process signal mask (data structure part of the process table managed by the kernel) shows which signals are being ignored, which are being caught, which are being temporarily blocked and which are in the process of being delivered.

» A blocked signal is not the same as an ignored signal. Its action is delayed until the process unblocks the pending signal.

Page 19: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 19Spring 2003

Signal Handling Example

#include <stdio.h> #include <signal.h>

/* signal handler function */ void action(int sig_no) { signal(sig_no, action); fprintf(stderr,"Catch signal: %d\n", sig_no); }

int main() { signal(SIGINT, action); signal(SIGALRM, SIG_DFL); signal(SIGTERM, SIG_IGN);

pause(); /* wait for a signal interruption */ }

Page 20: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 20Spring 2003

Delay execution

Pause system calll  pause system call suspends the calling process until a signal (which is

not ignored) will be received by invoking pause the process will no longer use CPU , while waiting for

the event; thus busy waiting is avoided]

#include <unistd.h>

unsigned pause();

Page 21: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 21Spring 2003

Alarm Handling

Alarm system function Sets a timer for the caller process and generates SIGALRM (signal

number 14) after the specified number of seconds have passed.

#include <unistd.h>

unsigned alarm(unsigned nosec);

Page 22: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 22Spring 2003

Alarm Handling

Example, alarm system calls cannot be stacked:

int main(void) {

alarm(20);

while (1)

fprintf(stderr,"Hello\n");

}

alarm(10);

alarm(20);

// when this system call is invoked

// the previous pending

// alarm signal is canceled;

// the timer is set to 20sec

alarm(0);

// this system call reset the timer, // any pending alarm system call is canceled

Page 23: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 23Spring 2003

Simulating sleep by using alarm and pause

// // Simulating sleep by using alarm and pause // #include <stdio.h> #include <signal.h> #include <unistd.h>  void wakeup() { }; unsigned int sleep ( unsigned int timer ) {  if (sigset(SIGALRM, wakeup)==-1) { perror("sigset"); return 1; }  (void)alarm( timer ); (void)pause(); return 0;

}

Page 24: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 24Spring 2003

Example of Handling Time-out Situations

#include <stdio.h> #include <unistd.h> #include <signal.h>

int main(void) { char buf[256];

int n;

signal(SIGALRM, timeout); alarm(30); // set timer

while ((n=read(0,buf,sizeof(buf))<0) ; alarm(0); // reset timer exit(0);

}

void timeout() {

fprintf(stderr,"Timeout error\n");

exit(0);

}

Page 25: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 25Spring 2003

Example:

A parent forks 10 children processes, each child sleep a random number of seconds . Parent process waits for child processes to terminate. Once a child process has terminated, then the parent will terminate all the remaining child processes, by signaling SIGTERM to each of them.#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <sys/wait.h> #include <signal.h> #include <stdlib.h>

int main() {pid_t p, q; int i, n, status;

for (i=0; i<10 ; i++) { if ((p=fork())<0) { fprintf(stderr, "cannot fork\n"); exit(1); } if (pid == 0) break; }

Page 26: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 26Spring 2003

Example: variant 1

if (p==0) /* child code */ { n = (int)(getpid()%256); srand((unsigned)pid); sleep(rand() %5);

} else /* parent code */ {

if ((q=waitpid(0,&status,0))>0) { kill(0,SIGTERM);

while ((q=wait(&status)) && q !=-1) { if (q!=-1) { if (WIFSIGNALED(status)) fprintf(stderr, "Child with PID = %d has received signal %04X\n",q,WTERMSIG(status); } } } } exit(0); }

Page 27: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 27Spring 2003

Example:variant 2

if (p==0) /* child code */ { signal(SIGTERM, action);

n = (int)(getpid()%256); srand((unsigned)pid); sleep(rand() %5);

} else /* parent code */ {

if ((q=waitpid(0,&status,0))>0) { kill(0,SIGTERM);

while ((q=wait(&status)) && q !=-1) { if (q!=-1) { if (WIFSIGNALED(status)) fprintf(stderr, "Child with PID = %d has received signal %04X\n",q,WTERMSIG(status); } } } } exit(0); }

void action() {

pid_t pid;

pid=getpid();

fprintf(stderr, "Child with PID = %d is terminating with SIGTERM\n",pid);

kill(pid, SIGTERM); /* raise(SIGTERM); */

}

Page 28: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 28Spring 2003

Solutions for Concurrency and I/O Non-determinism

Use nonblocking I/O– use fcntl() to set O_NONBLOCK

Use alarm and signal handler to interrupt slow system calls. Use multiple processes/threads. Use functions that support checking of multiple input sources at the

same time.

Page 29: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 29Spring 2003

Non blocking I/O

use fcntl() to set O_NONBLOCK:

#include <sys/types.h>#include <fcntl.h>

int flags;int pipe_fd[2];….flags = fcntl(pipe_fd,F_GETFL,0);fcntl(pipe_fd,F_SETFL,flags | O_NONBLOCK);

Now calls to read() (and other system calls) will return an error and set errno to EWOULDBLOCK.

Page 30: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 30Spring 2003

while (! done) {

if ( (n=read(STDIN_FILENO,…)<0))

if (errno != EWOULDBLOCK)

/* ERROR */

else write(pipe_fd[1],…)

if ( (n=read(pipe_fd[0],…)<0))

if (errno != EWOULDBLOCK)

/* ERROR */

else write(STDOUT_FILENO,…)

}

Page 31: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 31Spring 2003

The problem with nonblocking I/O

Using blocking I/O allows the Operating System to put the process to sleep when nothing is happening (no input). Once input arrives the OS will wake up the process and read() (or write() … ) will return.

With nonblocking I/O the process will “busy-wait”, using inefficiently the CPU time

Page 32: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 32Spring 2003

Using alarms

Time-out handling with alarmssignal(SIGALRM, sig_alrm);

alarm(MAX_TIME);

read(STDIN_FILENO,…);

...

signal(SIGALRM, sig_alrm);

alarm(MAX_TIME);

read(fd_pipe,…);

...

Issues:– How to assess the impact on response time ?

– How to choose the value for MAX_TIME?

Page 33: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 33Spring 2003

Using sigset()

sigset() makes use of a signal mask of type sigset t (array of long integers) where signals to be blocked are recorded

when sigset() is called the system add the sig value to the process's current signal mask before executing the catcher.

when catcher() finishes the system restores the signal mask; hence, unlike signal(), sigset() installed catcher() remain installed after the call.

when successful, sigset() returns either SIG HOLD, indicating that signal was previously blocked, or the disposition previously associated with the signal.

Page 34: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 34Spring 2003

Example using sigset()

/* Catching signals with sigset() */ #include <stdio.h>#include <signal.h> #include <unistd.h> #include <stdlib.h>extern int errno; int main(void) {int i; void SigCatcher(int);

if (sigset(SIGINT, SigCatcher) == SIG_ERR) { perror(''Sigset cannot set SIGINT''); exit(SIGINT); }if (sigset(SIGQUIT, SigCatcher) == SIG_ERR) {perror(''Sigset cannot set SIGQUIT''); exit(SIGQUIT); }

Page 35: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 35Spring 2003

Example using sigset()

for (i = 0; ; ++i) /* loop forever */

{

printf(''i = %d``n'', i);

sleep(1);

}

}

void SigCatcher( int signum)

{

printf(''\nSignal %d received.\n'', signum);

if (signum == SIGQUIT)

exit(1);

}

Page 36: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 36Spring 2003

Manipulating signal mask

a call to int sighold( int sig ); will add sig to the calling process signal mask;

a call to int sigrelse( int sig ); will remove sig from the calling process signal mask;

a call to int sigpause( int sig ); will remove sig from the signal mask and will suspend process until sig is received

a call to int sigignore( int sig ); will cause sig to be ignored (achievable by signal(sig, SIG_IGN))

Page 37: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 37Spring 2003

Example: Demonstration of sighold() and sigset()

Example: /* Demonstration of sighold() and sigset() */ /* Execute with a.out &; then type ''%kill USR1 pid'' and ''%kill USR2 pid'' */ #include <stdio.h> #include <signal.h> #include <unistd.h>

void SigCatcher( int n ) {printf(''Received signal %d will release SIGUSR1 \n'', n); sigrelse(SIGUSR1); printf(''SIGUSR1 released! \n''); }

int main(void) {

sighold(SIGUSR1); /* block signals SIGUSR1 */ sigset (SIGUSR2, SigCatcher); /* catch signals SIGUSR2 */ printf(''Waiting for signals\n''); pause (); printf (''Done\n''); exit(0);

}

Page 38: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 38Spring 2003

Using sigpause() system call

/* Pausing with sigpause() */

/* Run with a.out &; then type ''kill USR1 pid */

/* Try to kill process by ''kill INT pid'' after ''Beginning ...'' */

#include <stdio.h>

#include <signal.h>

#include <unistd.h>

void main(void)

{

void SigCatcher(int);

sigset(SIGUSR1, SigCatcher);

while ( 1 ) /* repeat forever */

}

printf(''Waiting for signal %d \n'', SIGUSR1);

sigpause (SIGUSR1);

}

void SigCatcher(int n)

{

sighold(SIGINT);

sighold(SIGTERM);

printf(''Beginning important stuff`\n'');

sleep(10);

printf(''Ending important stuff`\n'');

sigrelse(SIGTERM);

sigrelse(SIGINT);

}

Page 39: TDC368 UNIX and Network Programming

UNIX Network Programming – TDC368-901 Page 39Spring 2003

Observations

When SIGUSR1 is received the signal catching function is executed; during this time SIGINT and SIGTERM are blocked;

A set of messages indicating the beginning and the end of an important section of code are displayed

SIGINT and SIGTERM are then released;

hence typing ''kill INT pid'' will terminate the process.