280 likes | 435 Views
Lab #8 Signals. Operating System Lab. What Are Signals?. A signal is used by the OS to notify a process that a particular event has occurred. All signals follow the same pattern: A signal is generated by the occurrence of a particular event. A generated signal is delivered to a process.
E N D
Lab #8Signals Operating System Lab
What Are Signals? • A signal is used by the OS to notify a process that a particular event has occurred. • All signals follow the same pattern: • A signal is generated by the occurrence of a particular event. • A generated signal is delivered to a process. • Once delivered, the signal must be handled. • Every signal may be handled by one of two possible handlers: • A default signal handler • A user-defined signal handler NCHU System & Network Lab
Generating Signals Every signal has a symbolic name starting with SIG. The signal names are defined in signal.h Each signal is represented by small integers greater than 0. NCHU System & Network Lab
Generating Signals NCHU System & Network Lab
Generating Signals (cont.) NCHU System & Network Lab
Sending Signals Using the keyboard There are certain key presses that are interpreted by the system as requests to send signals to the process. Ctrl-C Causes the system to send an INT signal (SIGINT) to the running process. By default, this signal causes the process to immediately terminate. Ctrl-Z Causes the system to send a TSTP signal (SIGTSTP) to the running process. By default, this signal causes the process to suspend execution. Ctrl-\ Causes the system to send a ABRT signal (SIGABRT) to the running process. By default, this signal causes the process to immediately terminate. NCHU System & Network Lab
Sending Signals (cont.) From the command line signal_name: a symbolic name for the signal formed by omitting the leading SIG from the corresponding symbolic signal name. If no signal_name is specified, the TERM signal is sent. SYNOPSIS kill -s signal_name pid kill [-signal_name] pid kill [-signal_number] pid NCHU System & Network Lab
Example The following command is the traditional way to send signal number 9 (SIGKILL) to process 3423. kill -9 3423 The following command sends the SIGUSR1 signal to process 3423. kill -s USR1 3423 The following command sends the INT signal to process 3423. kill -INT 3423 The following command sends the TERM signal to process 3423, and therefore the process 3423 is terminated. kill 3423 NCHU System & Network Lab
Sending Signals (cont.) Using system calls This is the normal way of sending a signal from one process to another. Example: A child process sends the SIGTERM signal to its parent process. kill(getppid(), SIGTERM); SYNOPSIS #include <signal.h> int kill(pid_t pid, int sig); Return 0 if successful, -1 if unsuccessful NCHU System & Network Lab
alarm() Function Causes a SIGALRM signal to be sent to the calling process after a specified number of real seconds has elapsed. A value of seconds of 0 will turn off the timer. Calling alarm() before the signal is received will cause the alarm to be rescheduled. SYNOPSIS #include <unistd.h> unsigned alarm(unsigned seconds); NCHU System & Network Lab
Catching and Ignoring Signals What is a signal handler? The function to handle a signal. Default Signal Handlers If you install no signal handlers of your own, the runtime environment sets up a set of default signal handlers for your program. For example, the default signal handler for the TERM signal calls the exit()system call. NCHU System & Network Lab
Catching and Ignoring Signals (cont.) Installing Signal Handlers signal(), sigaction() signal: is used to set a signal handler for a single signal type. pause: causes the process to halt execution, until a signal is received. It is surely better than a 'busy wait' infinite loop. SYNOPSIS #include <signal.h> void (*signal(int sig, void (*func)(int)))(int); SYNOPSIS #include <unistd.h> int pause(void);
Catching and Ignoring Signals (cont.) Example /* here is the signal handler */ void catch_int(int sig_num) /* the argument is signal number */ { /* re-set the signal handler again to catch_int, for next time */ signal(SIGINT, catch_int); printf(“Ouch! – I got signal %d\n"); } int main(int argc, char* argv[]) { /* set the INT (Ctrl-C) signal handler to 'catch_int' */ signal(SIGINT, catch_int); /* now, lets get into an infinite loop of doing nothing. */ for ( ;; ) pause(); } NCHU System & Network Lab
Catching and Ignoring Signals (cont.) Pre-defined Signal Handlers: We can use two pre-defined signal handler functions, instead of writing our own. SIG_IGN: Ignore the specified signal. SIG_DFL: Restore default behavior. One problem with the early versions of UNIX is that the action of a signal was reset to its default each time the signal occurred. NCHU System & Network Lab
Exercise Write a simple signal handler that catches either of the two user defined signals and prints the signal number. Put the process to sleep until a signal is received. Then, we invoke the program in the background and use the killcommand to send it signals. NCHU System & Network Lab
Catching and Ignoring Signals (cont.) sigaction: allows the caller to examine or specify the action associated with a specific signal. The sigaction structure, used to define the actions to be taken on receipt of the signal specified by sig. SYNOPSIS #include <signal.h> int sigaction(int sig, const struct sigaction *act, struct sigaction *oact); Return 0 if successful, -1 if unsuccessful • struct sigaction { • void (*) (int) sa_handler;/* pointer to function, SIG_DFL or SIG_IGN */ • sigset_t sa_mask;/* additional signals to be blocked during execution of handler */ • int sa_flags; /* signal action modifiers */ • } NCHU System & Network Lab
Catching and Ignoring Signals (cont.) sig: specifies the signal number for the action act: a pointer to a struct sigaction structure that specifies the action to be taken If act is NULL, the call to sigaction() does not change the action associated with the signal. oact: a pointer to a struct sigaction structure that receives the previous action associated with the signal If oact is NULL, the call to sigaction() does not return the previous action associated with the signal. NCHU System & Network Lab
Catching and Ignoring Signals (cont.) sa_flags signals caught with handlers set by sigaction() are by default not reset. the sa_flags field must be set to contain the value SA_RESETHAND if we wish to obtain the behavior we saw earlier with signal. NCHU System & Network Lab
Examples 1. The following code segment sets the signal handler for SIGINT to mysighand. struct sigaction newact; newact.sa_handler = mysighand; /* set the new handler */ sigemptyset(&newact.sa_mask); /* initialize the signal mask */ newact.sa_flags = 0; /* no special options */ sigaction(SIGINT, &newact, NULL); 2. The following code segment causes the process to ignoreSIGINT if the default action is in effect for this signal. struct sigaction act; sigaction(SIGINT, NULL, &act); /* Find current SIGINT handler */ if (act.sa_handler == SIG_DFL) { /* if SIGINT handler is default */ act.sa_handler = SIG_IGN; /* set new SIGINT handler to ignore */ sigaction(SIGINT, &act, NULL); } NCHU System & Network Lab
Signal Masks and Signal Sets A process can temporarily prevent a signal from being delivered by blocking it. This signal mask is the set of signals that are currently blocked and therefore not be received by the current process. The signal mask is of type sigset_t. Blocking a signal is different from ignoring a signal. When a process blocks a signal, the operating system does not deliver the signal until the process unblocks the signal. A process blocks a signal by modifying its signal mask with sigprocmask. When a process ignores a signal, the signal is delivered and the process handles it by throwing it away. NCHU System & Network Lab
Signal Masks and Signal Sets (cont.) Functions used to manipulate sets of signals: SYNOPSIS #include <signal.h> int sigaddset(sigset_t *set, int signo); // adds signo to the signal set int sigdelset(sigset_t *set, int signo); // removes signo from the signal set int sigemptyset(sigset_t *set); // initializes a sigset_t to contain no signals int sigfillset(sigset_t *set); // initializes a sigset_t to contain all signals. int sigismember(sigset_t *set, int signo); // reports whether signo is in a sigset_t. NCHU System & Network Lab
Example /* define a new mask set */ sigset_t mask_set; /* first clear the set (i.e. make it contain no signal numbers) */ sigemptyset(&mask_set); /* lets add the TSTP and INT signals to our mask set */ sigaddset(&mask_set, SIGTSTP); sigaddset(&mask_set, SIGINT); /* and just for fun, lets remove the TSTP signal from the set. */ sigdelset(&mask_set, SIGTSTP); /* finally, lets check if the INT signal is defined in our set */ if(sigismember(&mask_set, SIGINT) printf("signal INT is in our set\n"); else printf("signal INT is not in our set - how strange...\n"); /* finally, lets make the set contain ALL signals available on our system */ sigfillset(&mask_set) NCHU System & Network Lab
Signal Masks and Signal Sets (cont.) A process can examine or modify its process signal mask with the sigprocmask fuction. how: specifies the manner in which the signal mask is to be modified, can take on one of the following three values. SIG_BLOCK: The signals in set are added to the signal mask. SIG_UNBLOCK: The signals in set are removed from the signal mask. SIG_SETMASK: The signal mask is set from set. SYNOPSIS #include <signal.h> int sigprocmask(int how, const sigset_t *set, sigset_t *oset); NCHU System & Network Lab
Signal Masks and Signal Sets (cont.) set: a pointer to a signal set to be used in the modification. If set is NULL, no modification is made. oset: If oset is not NULL, the sigprocmask returns in oset the signal set before the modification. Example • sigset_t new_set; • sigprocmask(SIG_SETMASK,&new_set,NULL); // The signal mask is set from new_set • The following code segment adds SIGINT to the set of signals that the process has blocked. • sigset_t new_set; • sigemptyset(&new_set); • sigaddset(&new_set, SIGINT); • sigprocmask(SIG_BLOCK, &new_set, NULL);
Lab I – An Alarm Clock Object: To simulate an alarm clock. First, we use fork() to create another process. The child process waits for five seconds before sending a SIGALRM signal to its parent. hint: sleep(nsec) halts process in nsec seconds. The parent process catches SIGALRM by first installing a signal handler using sigaction()and then waits for the sure occurrence of the signal. NCHU System & Network Lab
Lab II – Blocking and Unblocking a signal First, we block the SIGINT signal and increment the variable y eight times. wait for one second between each calculation. Then, unblock the signal, and do it the same times. The program repeats this sequence continually in a loop. NCHU System & Network Lab
Lab II – Blocking and Unblocking a signal NCHU System & Network Lab
References • Avi Silberschatz, Peter Baer Galvin and Greg Gagne, “Operating System Concepts,” John Wiley & Sons, 6th Edition, 2001 • “Unix Systems Programming: Communication, Concurrency, and Threads” by Kay A. Robbins, Steven Robbins • Neil Matthew and Richard Stones, “Beginning Linux Programming,” Wiley publishing, 3rd Edition, 2004 • W. Richard Stevens, “Advanced Programming in the UNIX Environment,” Addison-Wesley, 1992 • http://users.actcom.co.il/~choo/lupg/tutorials/signals/signals-programming.html NCHU System & Network Lab