overview
play

Overview Last Week: How to program UNIX processes (Chapters 7-9) - PDF document

Overview Last Week: How to program UNIX processes (Chapters 7-9) fork() and exec() Unix System Programming This Week: Signals UNIX inter-process communication mechanism: signals, pipes and FIFOs. How to program with UNIX signals


  1. Overview Last Week: � How to program UNIX processes (Chapters 7-9) � fork() and exec() Unix System Programming This Week: Signals � UNIX inter-process communication mechanism: signals, pipes and FIFOs. � How to program with UNIX signals (Chapter 10) � Non-local jumps (Chapter 7) � Focus on the sigaction() function 1 2 Maria Hybinette, UGA Maria Hybinette, UGA Outline What is a Signal? � What is a UNIX signal? � A signal is an asynchronous event which is delivered to a process (instantiated by a small � Signal types message) � Generating signals � Asynchronous means that the event can occur � Responding to a signal at any time � Common uses of a signal » may be unrelated to the execution of the process � Implementing a read() time-out » e.g. user types Ctrl-C , or the modem hangs � Non-local jumps setjmp()/longjmp() � Sent from kernel (e.g. detects divide by zero ( SIGFPE ) or could be at the request of another � POSIX signals process to send to another) � Interrupted system calls � Only information that a signal carries is its � System calls inside handlers unique ID and that it arrived 3 4 Maria Hybinette, UGA Maria Hybinette, UGA Signal Types (31 in POSIX) Signal Sources terminal memory ID Name Description Default Action driver management shell command Interrupt from keyboard ( ^C ) 2 SIGINT terminate SIGINT SIGHUP 3 SIGQUIT Quit from keyboard ( ^\ ) terminate & core SIGQUIT 9 SIGKILL kill -9 terminate SIGKILL kernel SIGPIPE 11 SIGSEGV Invalid memory reference terminate & core 14 SIGALRM alarm() clock ‘rings’ terminate SIGWINCH SIGALRM 17 SIGCHLD Child stopped or terminated ignore window 16 SIGUSR1 user-defined signal type terminate manager a process SIGUSR1 � /usr/include/sys/iso/signal_iso.h on atlas other user processes 5 6 Maria Hybinette, UGA Maria Hybinette, UGA

  2. Generating a Signal kill() � Use the UNIX command: {saffron} ./fork_example #include <signal.h> {saffron} kill -KILL 6676 Terminating Parent, PID = 6675 int kill( pid_t pid, int signo ); Running Child, PID = 6676 » sends a SIGKILL signal to {saffron} ps PID TTY TIME CMD processor ID ( pid) 6676 � Send a signal to a process (or group of processes). 6585 ttyp9 00:00:00 tcsh » check pid via (and also to 6676 ttyp9 00:00:06 fork_example � Return 0 if ok, -1 on error. {saffron} kill –s 9 6676 make sure it died) {saffron} ps PID TTY TIME CMD {saffron} ps -l Meaning � pid 6585 ttyp9 00:00:00 tcsh 6678 ttyp9 00:00:00 ps > 0 send signal to process pid � kill is not a good name; == 0 send signal to all processes send_signal might be whose process group ID equals the sender’s pgid . better. e.g. parent kills all children 7 8 Maria Hybinette, UGA Maria Hybinette, UGA Responding to a Signal signal() #include <signal.h> After receiving a signal a process can: � 1. Ignore/Discard/Block out the signal (not possible with void (*signal( int signo, void (*func)(int) ))(int); SIGKILL or SIGSTOP ) 2. Catch the signal; execute a signal handler function, and typedef void Sigfunc( int ); /* Plauger 1992 definition */ then possibly resume execution or terminate Sigfunc *signal( int signo, Sigfunc *handler ); 3. Carry out the default action for that signal � Signal returns a pointer to a function that returns an int (i.e. it The choice is called the process’ signal disposition returns a pointer to Sigfunc ) � � Specify a signal handler function to deal with a signal type. � Returns previous signal disposition if OK, SIG_ERR on error. 9 10 Maria Hybinette, UGA Maria Hybinette, UGA Sketch on how to program with 5. signal returns a pointer 4. The handler 2. The signal to be to a function. function signals Actual Prototype caught or ignored The return type is the same Receives a single is given as argument as the function that is passed integer signo in, argument and i.e., a function that takes an returns void � The actual prototype, listed in the “man” page is a bit int main() int and returns a void { perplexing but is an expansion of the Sigfunc type: signal( SIGINT, foo ); : void (*signal( int signo, void (*handler)(int)))(int); /* do usual things until SIGINT */ return 0; � signal returns a pointer to the previous signal handler } void foo( int signo ) 3. The function to { 6. The returned #include <signal.h> be called when the : /* deal with SIGINT signal */ 1. signal takes two function typedef void Sigfunc(int); /* Plauger 1992 */ specified signal is arguments: takes a integer Sigfunc *signal( int signo, Sigfunc *handler ); received is given as signo and handler return; /* return to program */ parameter. a pointer to the } function handler 11 12 Maria Hybinette, UGA Maria Hybinette, UGA

  3. External Signal Example: signal_example.c {saffron:ingrid:54} signal_example #include <stdio.h> int main( void ) 0: Received SIGUSR1 #include <signal.h> { 1: Received SIGUSR1 #include <unistd.h> int i = 0; 2: Received SIGUSR2 [1] + Stopped (signal) if( signal( SIGUSR1, sig_usr ) == SIG_ERR ) signal_example static void sig_usr( int signo ) perror( "Cannot catch SIGUSR1\n" ); {saffron:ingrid:26} fg signal_example { if( signal( SIGUSR2, sig_usr ) == SIG_ERR ) 3: Received SIGUSR1 if( signo == SIGUSR1 ) perror( "Cannot catch SIGUSR2\n" ); Quit printf( "Received SIGUSR1\n" ); else if( signo == SIGUSR2 ) while( 1 ) printf( "Received SIGUSR2\n" ); { {saffron:ingrid:55} kill -l= else printf( "%d: ", i ); {saffron:ingrid:56} ps -l { pause(); /* until signal handler fprintf( stderr, "ERROR: received signal %d\n", signo ); has processed signal */ {saffron:ingrid:23} kill -USR1 1255 exit(1); i++; {saffron:ingrid:24} kill -USR1 1255 } } {saffron:ingrid:25} kill -USR2 1255 return; return 0; {saffron:ingrid:26} kill -STOP 1255 {saffron:ingrid:27} kill -CONT 1255 } } {saffron:ingrid:28} kill -USR1 1255 {saffron:ingrid:29} kill QUIT 1255 13 14 Maria Hybinette, UGA Maria Hybinette, UGA Internal Signal Example: signal_example2.c Special Sigfunc * Values #include <stdio.h> int main( void ) #include <signal.h> { � Value Meaning #include <unistd.h> int i = 0; if( signal( SIGALRM, handler ) == SIG_ERR ) int beeps = 0; perror( "Cannot catch SIGALRM\n" ); alarm(1); Ignore / discard the signal. SIG_IGN static void handler( int signo ) while( 1 ) { { Use default action to handle signal. SIG_DFL printf( "BEEP\n" ); printf( "%d: ", i ); fflush(stdout); pause(); i++; } Returned by signal() as an error. SIG_ERR if( ++beeps < 5 ) return 0; alarm(1); } else { {cinnamon} signal_example2 printf("BOOM!\n"); 0: BEEP exit(0); 1: BEEP } 2: BEEP return; 3: BEEP 4: BEEP } BOOM! 15 16 Maria Hybinette, UGA Maria Hybinette, UGA Multiple Signals pause() � If many signals of the same type are waiting to #include <unistd.h> be handled (e.g. two SIGINT s), then most UNIXs int pause(void); will only deliver one of them. » the others are thrown away - i.e. pending signals are � Suspend the calling process until a signal is not queued caught. » for each signal type, just have a single bit indicating � Returns -1 with errno assigned EINTR . whether or not the signal has occured (Linux assigns it ERESTARTNOHAND ). � If many signals of different types are waiting to be handled (e.g. a SIGINT , SIGSEGV , SIGUSR1 ), � pause() only returns after a signal handler they are not delivered in any fixed order. has returned. 17 18 Maria Hybinette, UGA Maria Hybinette, UGA

  4. The Reset Problem Reset Problem Example � In Linux (and many other UNIXs), the signal int main() { disposition in a process is reset to its default signal(SIGINT, foo); action immediately after the signal has been : delivered. /* do usual things until SIGINT */ } void foo( int signo ) { � Must call signal() again to reinstall the signal(SIGINT, foo); /* reinstall */ signal handler function. : return; } 19 20 Maria Hybinette, UGA Maria Hybinette, UGA To keep catching the signal with this Reset Problem Re-installation may be too slow! function, must call the signal system call again. : � There is a (very) small time period in foo() when void ouch( int sig ) { a new SIGINT signal will cause the default action printf( "OUCH! - I got signal %d\n", sig ); to be carried out -- process termination. (void) signal( SIGINT, ouch ); Problem: from the time } � With signal() there is no answer to this that the interrupt function int main() starts to just before the problem. { signal handler is re- (void) signal( SIGINT, ouch ); established » POSIX signal functions solve it (and some other later while(1) the signal will not be UNIXs) { handled. printf( "Hello World!\n"); sleep(1); } If another SIGINT signal is } received during this time, default behavior will be done, i.e., program will terminate. 21 22 Maria Hybinette, UGA Maria Hybinette, UGA Common Uses of Signals Ignore a Signal : � Ignore a signal int main() { � Clean up and terminate signal( SIGINT, SIG_IGN ); signal( SIGQUIT, SIG_IGN ); � Dynamic reconfiguration : /* do work without interruptions */ � Report status } � Turn debugging on/off � Cannot ignore/handle SIGKILL or SIGSTOP � Restore a previous handler � Should check for SIG_ERR 23 24 Maria Hybinette, UGA Maria Hybinette, UGA

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend