CS代写 ICT374 Signal Handling

ICT374 Signal Handling
Signal Handling in UNIX
Objectives
• Understandtheconceptofsignalandsignalhandling mechanism

Copyright By PowCoder代写 加微信 powcoder

• Beabletowritesignalhandlers
• Beabletocatchandignoresignals
• Beabletoblockandunblocksignals
• Beawareoflimitationsofthetraditionalsignalmechanism
• Understandandbeabletousethenew,reliablesignalmodel and its programming interface
• Thislecturenotes
• Stevens&Rago:Ch10
• Stallings:Table2.6onpage124andTable6.2onpage316.
Page 1 of 29

ICT374 Signal Handling
1. Why Signals?
Signals are used to model asynchronous events (such as hardware interrupts). Asynchronous events are events that are likely to occur, but it is difficult to know whether they will occur. Even if you are sure that they will occur, you do not know when they will occur.
Examples of asynchronous events:
(1) Pressing CTRL-C to terminate a program
(2) Executing an illegal instruction
(3) Dividing by 0
(4) Child process notifying the parent process that it has terminated
(5) Operating system kernel notifying a process that its alarm clock had expired
(6) Reference to an Illegal memory address
(7) Modem connection hanging up
(8) Operating system kernel notifying a process that its window size has changed
Page 2 of 29

ICT374 Signal Handling
2. How to process asynchronous events?
(1) Polling the Device
For example, you may examine (poll) the terminal keyboard periodically to see whether the user has pressed the CRTL-C key.
Disadvantages:
(a) It wastes a lot of CPU time
(b) It is still possible to miss an event (which may be disastrous)
(c) It may need to poll many devices to ensure no event is missed
(d) It is difficult to write and understand such kind of programs
(2) Using the Interrupt Mechanism
A process keeps doing what it is supposed to do as if asynchronous events will never occur. However, once an event does occur, the interrupt mechanism would stop the execution of the current process, and then execute a piece of code for handling the event. After the code completes its execution, the OS kernel resumes the execution of the interrupted process.
Page 3 of 29

ICT374 Signal Handling
3. Signals
Signals model the asynchronous events. UNIX defines a set of 31 signals, each of which is represented by an integer number. Each signal represents one (or one type of) event(s). The following table lists some of the signals. Figure 10.1 of Stevens and Rago provides a full list of signals available in several important Unix- like operating systems.
Signal Symbolic Name
Signal Numeric Value
1 modem connection hangs up
2 interrupt the foreground
processes (CTRL-C)
3 terminate the foreground
processes (CTRL-\)
4 Illegal instruction
8 floating point error
9 Kill (cannot be caught or
11 Invalid memory reference
13 write to pipe that no one reads
14 Alarm clock expires
16 urgent condition occurred
18 stop the foreground processes
20 child process terminates
30 user-defined signal
31 user-defined signal
For the full list of signls, consult the header file which is file /usr/include/signal.h.
Page 4 of 29

ICT374 Signal Handling
4. Sending Signals
• Ausercansendsomesignalstoallprocessesinthe foreground process group by typing the following key combinations:
CTRL-C SIGINT CTRL-\ SIGQUIT CTRL-Z SIGTSTP
• TheUNIXkernelmaysendsomesignalstoaprocess,e.g., SIGALRM
• Aprocessmaysendasignaltoanotherprocess,eitherinthe program using the system call kill:
retval = kill (pid, signo)
or from the command line using the command kill:
% kill -SIGKILL 1001
% kill -9 1001
• Aprocessmaygeneratesomesignalsduringitsexecution (actually generated by the hardware)
SIGILL – executing an illegal instruction SIGSEGV – illegal address reference
Page 5 of 29

ICT374 Signal Handling
5. Handling Signals
When a signal arrives, the receiving process may choose to:
(a) ignore the signal (so nothing happens) (However, a process cannot ignore SIGKILL)
(b) stop the execution of the process to perform the default operation associated with the signal
(c) catch the signal, i.e., stop the execution of the process to perform a predefined operation
In the old UNIX system, signals were handled through the use of the signal function. Under the old signal model, a signal is either processed or ignored. If the receiving process does not have enough time to process all incoming signals immediately, some of those signals could be lost (without the receiving process knowing about it). Therefore, the old signal model is not reliable.
With the new signal model, the receiving process can block a signal if it does not want to process the signal immediately for whatever reason. The blocked signal is not lost, the process can unblock it later and then process it. The new signal model is reliable but has a more complicated programming interface.
In this topic, we will use the old signal function first, and discuss the new programming interface for reliable signal model later.
However, when writing a new program, you should use only the reliable signal interface (eg, sigaction), not the signal function. The function signal is now implemented with the reliable signal model (so it is reliable), however, it behaves differently on different Unix operating systems.
Page 6 of 29

ICT374 Signal Handling
6. Function Pointers
Before introducing the signal function, let’s review a couple of C language features. In C, a function is not a variable. However, we can declare a pointer variable that points to a particular type of functions. We can then invoke the function using that pointer variable instead of the function name.
Example 1: A void function that takes an integer parameter
void f1(int i)
printf(“This is function f1, i = %d\n”, i); }
void f2(int i)
printf(“This is function f2, i = %d\n”, i); }
Note: both f1 and f2 are functions, not variables. Example 2: A function pointer
The variable f in the following declaration is a pointer variable that points to a void function that takes an integer argument, which is similar to the functions such as f1 and f2 defined above.
void (*f) (int i);
Example 3: Compare the following three declarations:
(1) int ff (int n); (2) int *ff (int n); (3) int (*ff) (int n);
Page 7 of 29

ICT374 Signal Handling
In the above three declarations, the first ff is an integer function that takes an integer parameter. The second ff is a function that
takes an integer parameter and returns a pointer to an integer. The third ff is a pointer to a function that takes an integer parameter and returns an integer.
Example 4: Using a function pointer
Since the variable f declared in Example 2 is a pointer variable, we may assign the address of a compatible function to it. In C,
the function name itself, if used without parentheses, represents the starting address to that function. This is like an array variable whose name represents the starting address of the array. Therefore, we can do:
f(100); // same as f1(100);
f(200); // same as f2(200);
Compare this to an array and a pointer:
char line[] = “hello”; // array char *s; // pointer
s = line; // assign the start address
// of the array to pointer
// variable s
printf (“s = %s \n”, s); // print the string
// “hello”
Page 8 of 29

ICT374 Signal Handling
7. Setting Signal Handler (1) Signal Function (old)
#include
void (*signal( int signo, void (*handler)(int) ) )(int);
Install the new signal handler handler for signal signo and return the previous signal handler for signal signo.
It is not easy to read the above function prototype. However, if you focus on the red and green part from the above declaration, it would be easy to see
• thatsignalisjustafunctionthattakesanintegersigno and a function pointer handler (to a void function that takes an integer parameter).
• Thisfunction(signal)returnsapointertoavoidfunction that takes an integer parameter.
An alternative way to look at this function prototype is by redefine the signal with a new type (a void function taking an integer parameter):
typedef void sigfunc(int);
to define signal function:
sigfunc * signal(int signo, sigfunc * handler);
• signal is a function. It takes two parameters signo and
• Itreturnsapointertoavoidfunctionthattakesoneinteger parameter;
Page 9 of 29

ICT374 Signal Handling
Set the Default Signal Handler
signal (sig, SIG_DFL);
The system defined constant SIGN_DFL represents the default signal handler. The default operation for most signals is to terminate the receiving process.
Example 5: Kill a foreground process using CTRL-C
If you press “CTRL-C” on the terminal, the kernel would send thesignalSIGINTtotheforeground processtopwhich would then take the default action – terminate the itself.
Example 6: Send a signal to a background process % top &
% kill -SIGKILL 122
top (pid=122)
Page 10 of 29

ICT374 Signal Handling
(3) Ignore a Signals
signal (sig, SIG_IGN);
SIG_IGN is a system defined constant.
Example 7: Ignore a signal #include
int main() {
signal (SIGINT, SIG_IGN);
for ( ; ; ). // infinite loop
printf(“You cannot interrupt me!\n);
• typeCTRL-C(SIGINT)willnotstopthisprocess
• typeCTRL-\(SIGQUIT)willdo.
To restore the default signal handler, use:
signal (sig, SIG_DFL);
Page 11 of 29

ICT374 Signal Handling
Example 8: Ignore a signal and then restore the signal handler #include
int main() {
signal(SIGINT, SIG_IGN);
for (int i = 0; i < 20; ++i) { printf(“You cannot stop me now!\n); sleep (1); signal(SIGINT, SIG_DFL); for( ; ;){ //infiniteloop printf(“You can stop me now!\n”); sleep (1); Page 12 of 29 ICT374 Signal Handling (4) Catch a Signal Signal Table: for each process, the kernel keeps a signal table (in the kernel space, just like the Per Process Table of Open Files). The table keeps the address to the current signal handler for each signal. point to handler for signal 1 point to handler for signal 2 point to handler for signal 31 When a signal arrives, the normal execution of the receiving process is stopped, and the kernel retrieves the address of the signal handler from the Signal Table and then calls the signal handler for that signal. The signal handler is just a void function that takes one integer parameter. The kernel passes the signal number as the integer argument to the signal handler function. Once the signal handler returns, the kernel resumes the execution of the interrupted process. The user program may change the signal handler to a user- defined function using the signal function: void (*oldfunc)(int); // function pointer void newfunc(int) { . . . }; oldfunc = signal (sig, newfunc); Three special function pointers are defined in the Unix system, which have predefined meanings: (void (*) ()) -1 (void (*) ()) 0 (void (*) ()) 1 default operation ignore this signal Page 13 of 29 ICT374 Signal Handling Example 9: Catch SIGINT signals with signal function #include
void catch(int signo)
printf(“Signal %d is caught.\n”, signo); }
int main() {
signal(SIGINT, catch);
for (int i=0; i < 100; ++i) printf(“Sleep call %d\n”, i); sleep (1); } printf(“Exiting.\n”); exit(0); } • PressingCTL-Cwouldnotterminatetheprogram,because signal SIGINT would be caught by the program. • Similarly,using"kill–SIGINTpid"wouldnotkillthe program. Page 14 of 29 ICT374 Signal Handling 8. Alarm and Pause The following functions/system calls all have something to do with time. Here is a comparison: wait: pid = wait(&status) Suspend the calling process until one of its child processes terminates sleep: sleep(n) Suspend the calling process for a specified period of time (n seconds) alarm: remain=alarm(n) Set the calling process’ alarm clock to n seconds and return immediately. When the timer expires, the kernel will send the signal SIGALRM to the process. pause: pause() Suspend the calling process until a signal is received and the signal handler is executed and returned. Page 15 of 29 ICT374 Signal Handling Example 10: Use the alarm clock /* tml - tell me later program (adapted from Haviland) * usage example: tml 30 it is time to go home #include
#include
#include
int alarm_expired = 0; // set it to 1 once the alarm has expired void setflag (int signo) { alarm_expired = 1;} // signal handler
int main(int argc, char *argv[])
int nsecs, j;
pid_t pid;
if (argc <=2) fprintf(stderr, "Usage: %s #minutes message\n", argv[0]), if ((nsecs = atoi(argv[1])*60) <= 0) fprintf(stderr, "%s: invalid time\n", argv[0]), exit(2); pid = fork(); if (pid < 0) perror(" can't create process"), exit(3); else if (pid>0) // parent to quit, print child pid
printf(“%s: process id=%d\n”, argv[0], pid), exit(0);
// now only the child left
signal(SIGALRM, setflag); //install signal handler alarm(nsecs); // turn on alarm clock
pause(); // pause until signal
// now a has signal arrived and its signal handler executed if (alarm_expired) { // check whether this signal is SIGALRM
printf(“\007\007\007”); // ring bells
for (i=2; i
int sigemptyset (sigset_t *set);
int sigfillset (sigset_t *set);
int sigaddset (sigset_t *set, int signo); int sigdelset (sigset_t *set, int signo); int sigismember (sigset_t *set, int signo)
The functions sigemptyset and sigfillset are used to set a signal set to empty or to full set of signals. The functions sigaddset and sigdelset are used to add or delete an individual signal to or from a given signal set. These functions return 0 if successful or -1 on error. The function sigismember is used to test whether the given signal is in the specified signal set. This function returns 1 if the signal is in the set or 0 if it is not.
Page 20 of 29

ICT374 Signal Handling
Example 11: Create a sigset
The following code creates a signal set sigs with two signals:
SIGINT and SIGQUIT.
#include
sigset_t sigs;
if (sigemptyset(&sigs)==0) {
sigaddset(&sigs, SIGINT);
sigaddset(&sigs, SIGQUIT);
Setting the Signal Handler
We use the following function to change the signal handler:
int sigaction( int signo,
const struct sigaction *act,
struct sigaction *oldact);
act points to the structure containing the information of the new handler for the signal signo. If oldact is not NULL, the structure containing the existing signal handler is copied to oldact.
The sigaction structure is defined as
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
where one of the two function pointers, either sa_handler or sa_sigaction, points to the signal handler function. If sa_flags does not contain SA_SIGINFO flag then sa_handler
Page 21 of 29

ICT374 Signal Handling
points to the new signal handler function while sa_sigaction is redundant. Otherwise, sa_sigaction points to the new signal handler with three arguments:
void func_name(int, siginfo_t *, void * );
When a signal is received, the signal handler pointed to by sa_handler or sa_action is called. During the execution of the signal handler, additional signals with the same signal number are automatically blocked until the execution is finished.
Other signals can also be blocked during the execution of the signal handler. This set of signals is defined in sa_mask.
sa_flags modifies the behaviors of the signal handling process. For example if sa_flags=SA_RESETHAND, then the signal
handler is reset to the default once the handler is called (as in SVR4). Note POSIX.1 only defines one flag: SA_NOCLDSTOP (if signo is SIGCHLD, do not receive notification when child processes stop, e.g., when a child process is stopped by CTRL- Z).
Page 22 of 29

ICT374 Signal Handling
Example 12: Catch SIGINT signals with signaction #include
#include
void catch(int signo)
printf(“Signal %d caught\n”, signo);
sleep (4);
printf(“Signal %d returns\n”, signo);
int main() {
struct sigaction act;
act.sa_flags = 0;
act.sa_handler = c

程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com