Download presentation
Presentation is loading. Please wait.
Published byJerome Powell Modified over 8 years ago
1
CHAPTER 10. SIGNALS System Programming 本份投影片大量參考熊博安教授的系統程式投影片 羅習五 國立中正大學資訊工程學系 shiwulo@cs.ccu.edu.twshiwulo@cs.ccu.edu.twClass: EA-001 (05)2720411 ext. 33116Office: EA-517
2
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 2 Introduction Signals are software interrupts Handles asynchronous events user typing CTRL-C to stop a program next program in pipeline terminated prematurely Most implementations of signals were reliable and POSIX.1 standardized them
3
What is “signal” 3 user land kernel land system call signal (up call) hardware/software events kernel service
4
What is “signal” 4 time register a call back function my_sig_handler eventfunc div by 0default seg. faultdefault alarmmy_sig_handler ctr+cterminate ctr+/terminate
5
What is “signal” 5 time register a call back function my_sig_handler eventfunc div by 0default seg. faultdefault alarmmy_sig_handler ctr+cterminate ctr+/terminate
6
What is “signal” 6
7
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 7 Signal Concepts Every signal has a name. All begin with SIG. For example, SIGABRT : abort signal from abort() SIGALRM : alarm signal from alarm() These names are all defined by positive integer constants in the header
8
Signal Generation Terminal-generated signals: SIGINT Generated by hardware exceptions: SIGFPE: divide by 0 SIGSEGV: invalid memory reference Process generated signal kill(): send any signal to a process or process group (owner, superuser!) kill command: interface to kill() Software conditions: SIGURG: out-of-band network data SIGPIPE: pipe-write after pipe reader is terminated SIGALRM: alarm clock expires Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 8
9
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 9 Signal Disposition (Action) 1. IGNORE SIGNAL: all signals can be ignored, except SIGKILL and SIGSTOP Kernel or superuser can kill or stop a process, or Hardware exceptions leave process behavior undefined if signals ignored 2. CATCH SIGNAL: Call a function of ours when a signal occurs. Own shell: SIGINT return to main() Child terminated: SIGCHLD waitpid() Temporary files: SIGTERM clean up 3. DEFAULT ACTION: most are to terminate process (see next Figure!)
10
UNIX Signals (BSD) Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 10
11
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 11 UNIX Signals SIGABRT : signal from abort(), process terminates abnormally SIGALRM : timer set with alarm() expires SIGBUS : hardware fault (memory) SIGCHLD : child terminated, default action = ignore SIGCONT : sent to a stopped process to continue (default action), vi catches this signal to redraw terminal screen SIGEMT : hardware fault SIGFPE : arithmetic exception (floating point error; e.g, div by 0)
12
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 12 UNIX Signals SIGHUP : disconnect detected, session leader terminates, daemon processes reread configuration files SIGILL : Illegal hardware instruction SIGINFO : Terminal driver generates signal when we type status key (CTRL-T) SIGINT : Terminal driver generates signal when we type interrupt key (CTRL-C) SIGIO : Asynchronous I/O event
13
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 13 UNIX Signals SIGIOT : hardware fault (I/O trap) SIGKILL : to kill process by admin (cannot be caught or ignored) SIGPIPE : pipe write after pipe reader has terminated (same for socket) SIGPOLL : Specific event on pollable device SIGPROF : Profiling interval timer (set by setitimer) has expired
14
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 14 UNIX Signals SIGPWR : uninterruptible power supply (UPS) notifies a process of low power condition SIGQUIT : Terminal driver generates signal when we type quit key (CTRL-\) SIGSEGV : invalid memory reference SIGSTOP : Job-control signal to stop process, cannot be caught or ignored SIGSYS : invalid system call SIGTERM : termination signal sent by kill
15
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 15 UNIX Signals SIGTRAP : hardware fault (trap to debugger) SIGTSTP : Terminal driver generates signal when we type suspend key (CTRL-Z) SIGTTIN : background process tries to read from controlling terminal SIGTTOU : background process tries to write to controlling terminal SIGURG : urgent condition has occurred (out-of-band network data) SIGUSR1 : user-defined for API SIGUSR2 : user-defined for API
16
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 16 UNIX Signals SIGVTALRM : virtual interval timer set by setitimer(2) expired SIGWINCH : ioctl() changes window size SIGXCPU : process exceeds soft CPU time limit SIGXFSZ : process exceeds soft file size limit NULL signal: If signo is 0 the call does not send a signal, but it still performs error checking to test whether a process has suitable permissions to send the provided process a signal.
17
signal and process management Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 17 http://linux.vbird.org/linux_basic/0440processcontrol.php
18
signal Function #include void (*signal(int signo, void (*func)(int))) (int); Returns: previous disposition of signal if OK, SIG_ERR on error signo: SIGXXX signal name func: SIG_IGN, or SIG_DFL, or user-defined function (signal handler) Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 18
19
Figure 10.2: signal Function 1.#include “apue.h" 2. 3.static void sig_usr(int); /*handler for both signals*/ 4. 5.int main(void) { 6. if (signal(SIGUSR1, sig_usr) == SIG_ERR) 7. err_sys("can't catch SIGUSR1"); 8. if (signal(SIGUSR2, sig_usr) == SIG_ERR) 9. err_sys("can't catch SIGUSR2"); 10. for ( ; ; ) pause(); 11.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 19
20
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 20 Figure 10.2: signal Function 1.static void 2.sig_usr(int signo)/* argument is signal number */ 3.{ 4. if (signo == SIGUSR1) 5. printf("received SIGUSR1\n"); 6. else if (signo == SIGUSR2) 7. printf("received SIGUSR2\n"); 8. else err_dump("received signal %d\n", signo); 9. return; 10.}
21
Figure 10.2: results $./a.out & /* “&” make the process as a background process*/ [1] 7216 $ kill –USR1 7216 received SIGUSR1 $ kill –USR2 7216 received SIGUSR2 $ kill 7216 (SIGTERM not caught) [1] + Terminated./a.out Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 21
22
Lab 1 列印所有的 signal 1. #include 2. #include 3. #include 4. void sighandler(int signumber) { 5. printf("get a signal named '%d', '%s'\n", signumber, 6. sys_siglist[signumber]); 7. } 8. int main(int argc, char **argv) { 9. int sig_exist[100]; 10. int idx = 0; 11. for (idx = 0; idx < 100; idx++) { 12. if (signal(idx, sighandler) == SIG_ERR) { 13. sig_exist[idx] = 0; 14. } else { 15. sig_exist[idx] = 1; 16. } 17. } 18. for (idx = 0; idx < 100; idx++) { 19. if (sig_exist[idx] == 1) 20. printf("%2d %s\n", idx, sys_siglist[idx]); 21. } 22. printf("my pid is %d\n", getpid()); 23. printf("press any key to resume\n"); 24. getchar(); 25. } Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 22
23
make your code more readable $man indent The indent program can be used to make code easier to read. It can also convert from one style of writing C to another An Example /*a compact style*/ indent -kr -br -brf lab1.c 23
24
Lab 1: results (MAC OS X) 1 Hangup 2 Interrupt 3 Quit 4 Illegal instruction 5 Trace/BPT trap 6 Abort trap 7 EMT trap 8 Floating point exception 10 Bus error 11 Segmentation fault 12 Bad system call 13 Broken pipe 14 Alarm clock 15 Terminated 16 Urgent I/O condition 18 Suspended 19 Continued 20 Child exited 21 Stopped (tty input) 22 Stopped (tty output) 23 I/O possible 24 Cputime limit exceeded 25 Filesize limit exceeded 26 Virtual timer expired 27 Profiling timer expired 28 Window size changes 29 Information request 30 User defined signal 1 31 User defined signal 2 Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 24
25
Lab 1: results (Linux) 1 Hangup 2 Interrupt 3 Quit 4 Illegal instruction 5 Trace/breakpoint trap 6 Aborted 7 Bus error 8 Floating point exception 10 User defined signal 1 11 Segmentation fault 12 User defined signal 2 13 Broken pipe 14 Alarm clock 15 Terminated 16 Stack fault 17 Child exited 18 Continued 20 Stopped 21 Stopped (tty input) 22 Stopped (tty output) 23 Urgent I/O condition 24 CPU time limit exceeded 25 File size limit exceeded 26 Virtual timer expired 27 Profiling timer expired 28 Window changed 29 I/O possible 30 Power failure 31 Bad system call 34 (null) 35 (null) 36 (null) 37 (null) 38 (null) 39 (null) 40 (null) 41 (null) 42 (null) 43 (null) 44 (null) 45 (null) 46 (null) 47 (null) 48 (null) 49 (null) 50 (null) 51 (null) 52 (null) 53 (null) 54 (null) 55 (null) 56 (null) 57 (null) 58 (null) 59 (null) 60 (null) 61 (null) 62 (null) 63 (null) 64 (null) Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 25
26
Lab 1: results (Linux) 試試看 1. kill -4 uid 2. resize your terminal window 26
27
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 27 Program Start-up exec signals being caught default action (old handler has no meaning in new program) all other signals left alone gcc main.c & the shell automatically sets the disposition of the interrupt and quit signals in the background process to be ignored.
28
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 28 Signal disposition on fork On fork: Child inherits parent ’ s signal dispositions Old signal handler has meaning in child
29
unreliable signal??? Currently, most UNIX-like OSes support reliable signal. Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 29
30
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 30 Interrupted System Calls A process is blocked in a “ slow ” device (a system call) The process receives a signal The system call is interrupted and returns an error ( errno = EINTR ) May be something happened that should wake up the blocked system call
31
Why? 31 rdyQ running interruptible uninterruptible fork()_exit()
32
Interrupted System Calls System calls divided into 2 categories: slow: reads from or writes to files that can block caller forever (pipes, terminals, network devs) opens of files that block until some condition occurs (terminal waiting on modem answer) pause, wait some ioctl operations interprocessor communication all others: disk I/O, etc. Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 32
33
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 33 Interrupted System Calls Need to restart an interrupted system call 1.again: 2. if ( (n=read(fd, buf, BUFFSIZE)) < 0) { 3. if (errno==EINTR) goto again; 4. /* handle other errors */ 5. }
34
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 34 Interrupted System Calls POSIX.1 Allows implementation to restart interrupted system calls, but not required Single UNIX Spec (XSI extension) SA_RESTART flag to allow applications to request restart of interrupted system calls “Linux supports SA_RESTART”
35
Lab1: strace a.out rt_sigaction(SIGHUP, {0x4006ec, [HUP], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGINT, {0x4006ec, [INT], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGQUIT, {0x4006ec, [QUIT], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGILL, {0x4006ec, [ILL], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGTRAP, {0x4006ec, [TRAP], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGABRT, {0x4006ec, [ABRT], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGBUS, {0x4006ec, [BUS], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGFPE, {0x4006ec, [FPE], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGKILL, {0x4006ec, [KILL], SA_RESTORER| SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = -1 EINVAL (Invalid argument) 35
36
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 36 Interrupted System Calls
37
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 37 Reentrant Functions 1. Process is executing 2. Signal arrives and is caught 3. Signal handler starts executing 4. Signal handler returns 5. Process resumes execution summary: signal is an asynchronous event. so... Any problem?
38
38 time register a call back function my_sig_handler eventfunc div by 0default seg. faultdefault alarmmy_sig_handler ctr+cterminate ctr+/terminate
39
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 39 Reentrant Functions What if process was in the middle of malloc(), signal handler starts executing and also calls malloc()? malloc() maintains a linked list of all allocated areas process may have been in the middle of updating the linked list!
40
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 40 Reentrant Functions Functions that can be called by two or more processes (tasks, signal handlers), with arbitrary preemption (interrupt), and still give the same predictable output results. Use static variables in an atomic way, Do not call malloc or free, Does not belong to standard I/O library Reentrancy Conditions
41
Reentrant Functions (Linux) _exit accept access aio_error aio_return aio_suspend alarm bind bort cfgetispeed cfgetospeed cfsetispeed cfsetospeed chdir chmod chown clock_getti me close connect creat dup dup2 execle execve Exit fchmod fchown fcntl fdatasync fork fpathconf fstat fsync ftruncate getegid geteuid getgid getgroups getpeername getpgrp getpid getppid getsockname getsockopt getuid kill link listen lseek lstat mkdir mkfifo open pathconf pause pipe poll posix_trace _event pselect raise read readlink recv recvfrom recvmsg rename rmdir select sem_post send sendmsg sendto setgid setpgid setsid setsockopt setuid shutdown sigaction sigaddset sigdelset sigemptyset sigfillset sigismember signal sigpause sigpending sigprocmask sigqueue sigset sigsuspend sleep socket stat symlink tcdrain tcflow tcgetattr tcgetpgrp tcsetattr tcsetpgrp timer_getov errun timer_getti me times umask unlink utime wait waitpid write Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 41
42
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 42 Reentrant Functions Signal handlers should only call reentrant functions! “ errno variable” updated by reentrant functions such as read(), wait(), etc. signal handler should save errno, and restore it on exit
43
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 43 Figure 10.5: nonreentrant function call in signal handler 1.#include 2.#include “apue.h” 3.static void my_alarm(int); 4.int main(void) { 5. struct passwd *ptr; 6. 7. signal(SIGALRM, my_alarm); 8. alarm(1); 9. 10. for ( ; ; ) { 11. if ( (ptr = getpwnam("sar")) == NULL) 12. err_sys("getpwnam error"); Generates SIGALRM after 1 sec
44
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 44 Figure 10.5: nonreentrant function call in signal handler 1. if (strcmp(ptr->pw_name, "sar") != 0) 2. printf("return value corrupted!, pw_name = %s\n", 3. ptr->pw_name); 4. } 5.} 6. 7.static void 8.my_alarm(int signo) 9.{ 10. struct passwd *rootptr; 11. 12. printf("in signal handler\n"); 13. if ( (rootptr = getpwnam("root")) == NULL) 14. err_sys("getpwnam(root) error"); 15. alarm(1); 16.} A NONREENTRANT function called by both main() and signal handler
45
Figure 10.5: results Results are random Usually terminated by SIGSEGV Internal pointers corrupted when signal handler also called getpwnam() after main called it Sometimes terminated correctly, but return value sometimes corrupted and sometimes fine. 在 Linux 當中,這段程式碼幾乎不會有任何問題,但... 萬一... 不怕一萬,只怕萬一 Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 45
46
SIGCLD Semantics signal(SIGCLD, SIG_IGN) no zombie processes for children subsequent wait() will block until all children terminated and returns -1 with errno = ECHILD different from SIG_DFL (also ignore, but without the above semantics) signal(SIGCLD, handler) kernel checks for child to be waited for if there is, kernel calls SIGCLD handler Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 46
47
SIGCHLD Semantics POSIX.1 Does not specify what happens when SIGCHLD is ignored Single UNIX Specification (XSI extension) Same as for SIGCLD 4.4BSD and FreeBSD 5.2.1 Always generates zombies if SIGCHLD ignored SVR4, Solaris 9, Linux, Mac OS X 10.3 signal(SIGCHLD, SIG_IGN) zombies never generated Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 47
48
Figure 10.6: SIGCLD handler not working in System V 在目前的UNIX應該不會出現這個現象 如果於處理SIGCLD的signal內再呼叫signal 而出現問題時 請參考此章節 Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 48
49
這個問題類似 不用死記... 龘:三個「龍」唸ㄊㄚˋ 麤:三個「鹿」唸ㄘㄨ 驫:三個「馬」唸ㄅㄧㄠ 馫:三個「香」唸ㄒㄧㄥ 就算我們精通華文,上面的這些字也多半念不出來 有些東西,仿佛記得就好,不會再查書 49
50
Reliable Signal Terminology and Semantics Kernel sets a flag in the process table indicating that the signal is generated Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 50
51
Reliable Signal Terminology and Semantics Signal is DELIVERED to a process if action for signal is taken Between generation and delivery, signal is called PENDING A process can BLOCK the delivery of a signal using SIGNAL MASK Signal mask can be changed by sigprocmask() (see Section 10.12) Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 51
52
Reliable Signal Terminology and Semantics More than one blocked signal? Queued? No! Just once! SIGSEGV delivered first sigset_t: POSIX.1 data type to store signal mask #bits = #signals, Bit i = 1 signal i blocked Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 52
53
Lab5 #include void sighandler(int signumber) { printf("get a signal named '%d', '%s'\n", signumber, sys_siglist[signumber]); if (signumber == SIGINT) exit(0); } int main(int argc, char **argv) { int sig_exist[100]; sigset_t sigset; int idx = 0; for (idx = 0; idx < 100; idx++) { if (signal(idx, sighandler) == SIG_ERR) { sig_exist[idx] = 0; } else { sig_exist[idx] = 1; } for (idx = 0; idx < 100; idx++) { if (sig_exist[idx] == 1) printf("%2d %s\n", idx, sys_siglist[idx]); } printf("my pid is %d\n", getpid()); sigfillset(&sigset); sigprocmask(SIG_SETMASK, &sigset, NULL); printf("sleep 10sec\n"); for(idx=0; idx<10; idx++) { sleep(1); write(1, "*", 1); } printf("\n"); sigemptyset(&sigset); sigprocmask(SIG_SETMASK, &sigset, NULL); while (1) { pause(); } 53
54
Lab5: results... 63 (null) 64 (null) my pid is 7276 sleep 10sec *^\^\^\^\*^\^\^\^\**^\*^\***** get a signal named '3', 'Quit' ^Cget a signal named '2', 'Interrupt' 54
55
kill and raise functions kill: To send a signal to a process or a process group #include int kill(pid_t pid, int signo); Both return: 0 if OK, -1 on error Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 55
56
kill(pid_t pid, int signo) pid > 0: sent to PID==pid pid < 0: sent to PGID==|pid| pid == 0: sent to all processes with PGID == PGID of sender (with perm) pid == -1: all processes on the system for which the sender has permission to send signal (excluding system processes) Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 56
57
kill function Permission to send signals: Superuser: to any process Others: real/effective ID of sender must be equal to real/effective ID of receiver Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 57
58
alarm Function alarm() sets a timer to expire at a specified time in future when timer expires, SIGALRM signal is generated default action: terminate process #include unsigned int alarm(unsigned int seconds); Returns: 0 or #seconds until previously set alarm Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 58
59
alarm Function Process receives signal after the specified seconds seconds Processor scheduling delays may occur Only 1 alarm clock per process If we call alarm, and there is a previously registered alarm not expired #seconds left for the previous alarm to expire is returned new alarm replaces previous alarm alarm(0) a previous unexpired alarm is cancelled Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 59
60
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 60 pause Function Suspends a process until a signal is caught #include int pause(void); Returns: -1 with errno set to EINTR pause returns only if a signal handler is executed and that handler returns!
61
一些不太好的寫法 以 sleep 為例 61
62
man 3 sleep #include unsigned int sleep(unsigned int seconds); DESCRIPTION sleep() makes the calling thread sleep until seconds seconds have elapsed or a signal arrives which is not ignored. RETURN VALUE Zero if the requested time has elapsed, or the number of seconds left to sleep, if the call was interrupted by a signal handler. 62
63
Figure 10.7: using alarm and pause to implement sleep (incomplete) 1.#include 2.#include 3. 4.static void 5.sig_alrm(int signo) 6.{ 7. return; /* nothing to do, just return to wake up the pause */ 8.} 9. 10.unsigned int 11.sleep1(unsigned int nsecs) 12.{ 13. if (signal(SIGALRM, sig_alrm) == SIG_ERR) 14. return(nsecs); 15. alarm(nsecs); /* start the timer */ 16. pause(); /* next caught signal wakes us up */ 17. return( alarm(0) ); /* turn off timer, return unslept time */ 18.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 63 假如還沒呼叫 pause 之前, alarm 就發生了?
64
Figure 10.8: Another imperfect implementation of sleep 1.#include 2.#include 3.#include 4. 5.static jmp_buf env_alrm; 6. 7.static void sig_alrm(int signo) { longjmp(env_alrm, 1); } 8. 9.unsigned int sleep2(unsigned int nsecs) { 10. if (signal(SIGALRM, sig_alrm) == SIG_ERR) 11. return(nsecs); 12. if (setjmp(env_alrm) == 0) { 13. alarm(nsecs); /* start the timer */ 14. pause(); /* next caught signal wakes us up */ 15. } 16. return( alarm(0) ); /*turn off timer, return unslept time*/ 17.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 64
65
Figure 10.9: Calling sleep2 1.#include “apue.h" 2. 3.unsigned int sleep2(unsigned int); 4.static void sig_int(int); 5. 6.int main(void) { 7. unsigned int unslept; 8. 9. if (signal(SIGINT, sig_int) == SIG_ERR) 10. err_sys("signal(SIGINT) error"); 11. unslept = sleep2(5); 12. printf("sleep2 returned: %u\n", unslept); 13. exit(0); 14.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 65
66
Figure 10.9: Calling sleep2 1.static void sig_int(int signo) 2.{ 3. int i; 4. volatile int j; 5. 6. printf("\nsig_int starting\n"); 7. for (i = 0; i < 300000; i++) 8. for (j = 0; j < 4000; j++) 9. k += i * j; 10. /*底下這一行可能不會被呼叫到,因為在sig_alrm()中已經直 接longjmp回去*/ 11. printf("sig_int finished\n"); 12.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 66
67
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 67 Figure 10.9: results $./a.out ^? /* CTRL key pressed */ /* 照理說 ctr-c 應該打斷 sleep*/ sig_int starting /* 沒出現 “sig_int finished”*/ sleep2 returned: 0
68
活用 SIGNAL (正確、常用) 68
69
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 69 alarm: upper time limit on blocking operations A read operation on a “ slow ” device can block for a long time An upper time limit can be imposed using the alarm function and SIGALRM See next program (buggy!)
70
Figure 10.10: read with timeout 1.#include “apue.h" 2. 3.static void sig_alrm(int); 4. 5.int main(void) 6.{ 7. int n; 8. char line[MAXLINE]; 9. 10. if (signal(SIGALRM, sig_alrm) == SIG_ERR) 11. err_sys("signal(SIGALRM) error"); 12. alarm(10); 13. if ( (n = read(STDIN_FILENO, line, MAXLINE)) < 0) 14. err_sys("read error"); 15. alarm(0); 16. 17. write(STDOUT_FILENO, line, n); 18. 19. exit(0); 20.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 70 race condition between alarm and read, set minute- long time delay to circumvent race read not interrupted if interrupted system calls are automatically restarted
71
Figure 10.10: read with timeout 1.static void 2.sig_alrm(int signo) 3.{ 4. /* nothing to do, just return to interrupt the read */ 5.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 71
72
lab6 Figure 10.10 的寫法好嗎? 當 timeout 時真的會終止 read 嗎? 是否有更好的寫法? ( hint: sigaction w/o SA_RESTART ) 72
73
Figure 10.11: read with timeout (using longjmp) 1.#include 2.#include “apue.h" 3. 4.static void sig_alrm(int); 5.static jmp_buf env_alrm; 6. 7.int 8.main(void) 9.{ 10. int n; 11. char line[MAXLINE]; 12. 13. if (signal(SIGALRM, sig_alrm) == SIG_ERR) 14. err_sys("signal(SIGALRM) error"); 15. 16. if (setjmp(env_alrm) != 0) Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 73
74
Figure 10.11: read with timeout (using longjmp) 1.err_quit("read timeout"); 2. 3. alarm(10); 4. if ( (n = read(STDIN_FILENO, line, MAXLINE)) < 0) 5. err_sys("read error"); 6. alarm(0); 7. 8. write(STDOUT_FILENO, line, n); 9. 10. exit(0); 11.} 12. 13.static void 14.sig_alrm(int signo) 15.{ 16. longjmp(env_alrm, 1); 17.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 74 problem in interaction with other signal handlers
75
Signal Sets Signal set = a set of signals POSIX.1: sigset_t (data type to represent multiple signals) #include int sigemptyset (sigset_t *set); int sigfillset (sigset_t *set); int sigaddset (sigset_t *set, int signo); int sigdelset (sigset_t *set, int signo); Return: 0 if OK, -1 on error int sigismember (const sigset_t *set, int signo); Returns: 1 if true, 0 if false, -1 on error Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 75
76
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 76 sigprocmask Function Examine or change signals to be blocked #include int sigprocmask(int how, const sigset_t *set, sigset_t *oset); Returns: 0 if OK, -1 on error oset != NULL current mask returned in oset set != NULL current mask modified …
77
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 77 sigprocmask Function How to modify? (set != NULL, how = … )
78
Figure 10.14: print mask 1.#include 2.#include “apue.h" 3. 4.void pr_mask(const char *str) { 5. sigset_t sigset; 6. int errno_save; 7. 8. errno_save = errno; /*we can be called by signal handlers*/ 9. if (sigprocmask(0, NULL, &sigset) < 0) 10. err_sys("sigprocmask error"); 11. printf("%s", str); 12. if (sigismember(&sigset, SIGINT)) printf("SIGINT "); 13. if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT "); 14. if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 "); 15. if (sigismember(&sigset, SIGALRM)) printf("SIGALRM "); 16. /* remaining signals can go here */ 17. printf("\n"); 18. errno = errno_save; 19.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 78
79
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 79 sigaction Examine or modify a signal action Reliable Signals! #include int sigaction(int signo, const struct sigaction *act, struct sigaction *oact); Returns: 0 if OK, -1 on error nonnull modify action nonnull return action
80
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 80 sigaction 1.struct sigaction { 2./*addr of signal handler or SIG_IGN or SIG_DFL */ 3.void (*sa_handler)(int); 4./* additional signals to block */ 5.sigset_t sa_mask; 6./* signal options*/ 7.int sa_flags; 8./* alternate handler */ 9.void (*sa_sigaction)(int, siginfo_t *, void *); 10.};
81
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 81 sa_flags Check Figure 10.16 for sa_flags SA_INTERRUPT (not in standard, Linux only) SA_NOCLDSTOP (POSIX.1, all 4 platforms) SA_NOCLDWAIT (XSI, all 4 platforms) SA_NODEFER (XSI, all 4 platforms) SA_ONSTACK (XSI, all 4 platforms) SA_RESETHAND (XSI, all 4 platforms) SA_RESTART (XSI, all 4 platforms) SA_SIGINFO (POSIX.1, all 4 platforms)
82
Implementation of signal using sigaction (reliable semantics) 1.#include “apue.h" 2. 3./* Reliable version of signal(), using POSIX sigaction(). */ 4. 5.Sigfunc * 6.signal(int signo, Sigfunc *func) 7.{ 8. struct sigaction act, oact; 9. 10. act.sa_handler = func; 11. sigemptyset(&act.sa_mask); 12. act.sa_flags = 0; 13. if (signo == SIGALRM) { Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 82
83
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 83 Implementation of signal using sigaction 1.#ifdef SA_INTERRUPT 2. act.sa_flags |= SA_INTERRUPT; 3.#endif 4. } else { 5.#ifdef SA_RESTART 6. act.sa_flags |= SA_RESTART; 7.#endif 8. } 9. if (sigaction(signo, &act, &oact) < 0) 10. return(SIG_ERR); 11. return(oact.sa_handler); 12.}
84
signal (without restart) 1.#include “apue.h" 2. 3.Sigfunc * 4.signal_intr(int signo, Sigfunc *func) 5.{ 6. struct sigaction act, oact; 7. 8. act.sa_handler = func; 9. sigemptyset(&act.sa_mask); 10. act.sa_flags = 0; 11.#ifdef SA_INTERRUPT 12. act.sa_flags |= SA_INTERRUPT; 13.#endif 14. if (sigaction(signo, &act, &oact) < 0) 15. return(SIG_ERR); 16. return(oact.sa_handler); 17.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 84
85
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 85 sigsetjmp, siglongjmp Similar to setjmp and longjmp Difference: saves mask and restores it #include int sigsetjmp(sigjmp_buf env, int savemask); void siglongjmp(sigjmp_buf env, int val); Returns: 0 if called directly, nonzero if returning from siglongjmp
86
Figure 10.20: jmp functions 1.#include 2.#include 3.#include “apue.h" 4.static void sig_usr1(int), sig_alrm(int); 5.static sigjmp_buf jmpbuf; 6.static volatile sig_atomic_t canjump; 7. 8.int main(void) { 9. if (signal(SIGUSR1, sig_usr1) == SIG_ERR) 10. err_sys("signal(SIGUSR1) error"); 11. if (signal(SIGALRM, sig_alrm) == SIG_ERR) 12. err_sys("signal(SIGALRM) error"); 13. pr_mask("starting main: "); 14. 15. if (sigsetjmp(jmpbuf, 1)) { 16. pr_mask("ending main: "); 17. exit(0); } 18. canjump = 1; /* now sigsetjmp() is OK */ 19. for ( ; ; ) pause(); 20.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 86 Defined by ISO C Guaranteed atomic write (1)Does not extend across page boundaries (2)Accessed with a single machine instruction (3)Volatile: accessed by 2 threads: main and signal handler Defined by ISO C Guaranteed atomic write (1)Does not extend across page boundaries (2)Accessed with a single machine instruction (3)Volatile: accessed by 2 threads: main and signal handler
87
Figure 10.20: jmp functions 1.static void sig_usr1(int signo) { 2. time_t starttime; 3. 4. if (canjump == 0) 5. return; /* unexpected signal, ignore */ 6. 7. pr_mask("starting sig_usr1: "); 8. 9. alarm(3); /* SIGALRM in 3 seconds */ 10. 11. starttime = time(NULL); 12. for ( ; ; ) * busy wait for 5 seconds */ 13. if (time(NULL) > starttime + 5) break; 14. pr_mask("finishing sig_usr1: "); 15. 16. canjump = 0; 17. siglongjmp(jmpbuf, 1);/* jump back to main, don't return */ 18.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 87
88
Figure 10.20: jmp functions 1.static void sig_alrm(int signo) { 2. pr_mask("in sig_alrm: "); 3. return; 4.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 88
89
Time line for Figure 10.20 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 89
90
Figure 10.20: results $./a.out & starting main: [1] 531 $ kill –USR1 531 starting sig_usr1: SIGUSR1 $ in sig_alrm: SIGUSR1 SIGALRM finishing sig_usr1: SIGUSR1 ending main: [1] + Donea.out & Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 90
91
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 91 Without save/restore signals If we use setjmp, longjmp in Linux and Solaris, or _setjmp, _longjmp in FreeBSD, Mac OS X Final line of output: ending main: SIGUSR1 Main function is executing with SIGUSR1 blocked, after call to setjmp This is not what we want!
92
sigsuspend Function To protect critical section by blocking a signal 1.sigset_t newmask, oldmask; 2.sigemptyset(&newmask); 3.sigaddset(&newmask, SIGINT); 4.if(sigprocmask(SIG_BLOCK, &newmask, &oldmask), 0) 5. err_sys(“SIG_BLOCK error”); 6./* CRITICAL REGION OF CODE */ 7.if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 8. err_sys(“SIG_SETMASK error”); 9. 10. 11.pause(); Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 92 What if signal occurs HERE?
93
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 93 sigsuspend Function Reset signal mask & put process to sleep for a signal (1 atomic operation) #include int sigsuspend(const sigset_t *sigmask); Returns: -1 with errno set to EINTR No successful return
94
sigsuspend Function sigsuspend 的整个原子操作过程为: (1) 设置新的 mask 阻塞当前进程; (2) 收到信号,调用该进程设置的信号处理函数; (3) 待信号处理函数返回后,恢复原先 mask ; (4) sigsuspend 返回。 94 http://bbs.csdn.net/topics/290014298
95
Figure 10.22: sigsuspend 1.#include “apue.h" 2.static void sig_int(int); 3. 4.int main(void) { 5. sigset_t newmask, oldmask, waitmask; 6. pr_mask(“program start: “); 7. if (signal(SIGINT, sig_int) == SIG_ERR) 8. err_sys("signal(SIGINT) error"); 9. 10. sigemptyset(&waitmask); 11. sigaddset(&waitmask, SIGUSR1); 12. sigemptyset(&newmask); 13. sigaddset(&newmask, SIGINT); 14. /* Block SIGINT and save current signal mask */ 15. if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 16. err_sys("SIG_BLOCK error"); 17. 18. /* Critical region of code */ Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 95
96
Figure 10.22: sigsuspend 1. pr_mask("in critical region: "); 2. 3. /* Pause, allowing all signals except SIGUSR1 */ 4. if (sigsuspend(&waitmask) != -1) 5. err_sys("sigsuspend error"); 6. pr_mask("after return from sigsuspend: "); 7. 8. /* Reset signal mask which unblocks SIGINT */ 9. if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 10. err_sys("SIG_SETMASK error"); 11. /* And continue processing... */ 12. pr_mask(“program exit: “); 13. exit(0); 14.} 15. 16.static void sig_int(int signo) 17.{ pr_mask("\nin sig_int: "); return; } Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 96
97
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 97 Figure 10.22: results $./a.out in critical region: SIGINT ^? in sig_int: SIGINT SIGUSR1 after return from sigsuspend: SIGINT program exit: Restores mask to its value before the call to sigsuspend
98
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 98 Figure 10.23: wait for global variable using sigsuspend() 1.#include "apue.h" 2. 3.volatile sig_atomic_t quitflag; /* set nonzero by signal handler */ 4. 5.static void sig_int(int signo) 6. /* 1 signal handler for SIGINT and SIGQUIT */ 7.{ 8. if (signo == SIGINT) 9. printf("\ninterrupt\n"); 10. else if (signo == SIGQUIT) 11. quitflag = 1; /* set flag for main loop */ 12.}
99
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 99 Figure 10.23: wait for global variable using sigsuspend() 1.int main(void){ 2. sigset_t newmask, oldmask, zeromask; 3. 4. if (signal(SIGINT, sig_int) == SIG_ERR) 5. err_sys("signal(SIGINT) error"); 6. if (signal(SIGQUIT, sig_int) == SIG_ERR) 7. err_sys("signal(SIGQUIT) error"); 8. 9. sigemptyset(&zeromask); 10. sigemptyset(&newmask);
100
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 100 Figure 10.23: wait for global variable using sigsuspend() 1. sigaddset(&newmask, SIGQUIT); 2. 3. /* Block SIGQUIT and save current signal mask. */ 4. if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 5. err_sys("SIG_BLOCK error"); 6. 7. while (quitflag == 0) 8. sigsuspend(&zeromask);
101
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 101 Figure 10.23: wait for global variable using sigsuspend() 1./* SIGQUIT has been caught and is now blocked; do whatever. 2. */ 3. quitflag = 0; 4. 5. /* Reset signal mask which unblocks SIGQUIT. */ 6. if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 7. err_sys("SIG_SETMASK error"); 8. 9. exit(0); 10.}
102
Figure 10.23: results $./a.out ^? interrupt ^? interrupt ^? interrupt ^? interrupt ^? interrupt ^? interrupt ^\ $ Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 102
103
EXAMPLE 103
104
abort Function Causes abnormal program termination by sending SIGABRT to caller using raise(SIGABRT) #include void abort(void); Function never returns ISO C If SIGABRT caught and signal handler returns, abort still does not return to caller. exit, _exit, _Exit, longjmp, siglongjmp POSIX.1 Abort overrides blocking and ignoring of the signal by process Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 104
105
Implementation of POSIX.1 abort 1.#include 2.#include 3.#include 4.#include 5. 6.void abort(void) /* POSIX-style abort() function */ 7.{ 8. sigset_t mask; 9. struct sigaction action; 10. 11. /* Caller can't ignore SIGABRT, if so reset to default. */ 12. sigaction(SIGABRT, NULL, &action); 13. if (action.sa_handler == SIG_IGN) { 14. action.sa_handler = SIG_DFL; 15. sigaction(SIGABRT, &action, NULL); 16. } Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 105
106
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 106 Implementation of POSIX.1 abort 1.if (action.sa_handler == SIG_DFL) 2. fflush(NULL); /* flush all open stdio streams */ 3. 4. /* Caller can't block SIGABRT; make sure it's unblocked. */ 5. sigfillset(&mask); 6. sigdelset(&mask, SIGABRT); /* mask has only SIGABRT turned off */ 7. sigprocmask(SIG_SETMASK, &mask, NULL); 8. 9. kill(getpid(), SIGABRT); /* send the signal */
107
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 107 Implementation of POSIX.1 abort 1./* If we're here, process caught SIGABRT and returned. */ 2. fflush(NULL); /* flush all open stdio streams */ 3. action.sa_handler = SIG_DFL; 4. sigaction(SIGABRT, &action, NULL); /* reset to default */ 5. sigprocmask(SIG_SETMASK, &mask, NULL); /* just in case... */ 6. 7. kill(getpid(), SIGABRT); /* and one more time */ 8. 9. exit(1); /* this should never be executed... */ 10.}
108
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 108 system Function Signal handling for calling system() Must ignore SIGINT, SIGQUIT Must block SIGCHLD login shell a.out/bin/sh/bin/ed fork exec fork exec fork exec background process group foreground process group
109
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 109 system Function 1. #include 2. #include 3. #include 4. #include 5. 6. /* with appropriate signal handling */ 7. int system(const char *cmdstring) { 8. pid_t pid; 9. int status; 10. struct sigaction ignore, saveintr, savequit; 11. sigset_t chldmask, savemask; 12. 13. if (cmdstring == NULL) 14. /* always a command processor with UNIX */ 15. return(1);
110
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 110 system Function 1. /*ignore SIGINT and SIGQUIT */ 2. ignore.sa_handler = SIG_IGN; 3. sigemptyset(&ignore.sa_mask); 4. ignore.sa_flags = 0; 5. if (sigaction(SIGINT, &ignore, &saveintr) < 0) 6. return(-1); 7. if (sigaction(SIGQUIT, &ignore, &savequit) < 0) 8. return(-1); 9. sigemptyset(&chldmask); /* now block SIGCHLD */ 10. sigaddset(&chldmask, SIGCHLD); 11. if (sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0) 12. return(-1);
111
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 111 system Function 1. if ((pid = fork()) < 0) { 2. /* probably out of processes */ 3. status = -1; 4. } else if (pid == 0) { /* child */ 5. /* restore previous signal actions & reset signal mask */ 6. sigaction(SIGINT, &saveintr, NULL); 7. sigaction(SIGQUIT, &savequit, NULL); 8. sigprocmask(SIG_SETMASK, &savemask, NULL); 9. 10. execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); 11. _exit(127); /* exec error */ 12. }
112
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 112 system Function 1. else { /* parent */ 2. while (waitpid(pid, &status, 0) < 0) 3. if (errno != EINTR) { 4. status = -1; /* error other than EINTR from waitpid() */ 5. break; 6. } 7. } 8. /* restore previous signal actions & reset signal mask */ 9. if (sigaction(SIGINT, &saveintr, NULL) < 0) return(-1); 10. if (sigaction(SIGQUIT, &savequit, NULL) < 0) return(-1); 11. if (sigprocmask(SIG_SETMASK, &savemask, NULL) < 0) return(-1); 12. return(status); 13. }
113
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 113 sleep Function #include unsigned int sleep(unsigned int seconds); Returns 0 or number of unslept seconds Causes process to be suspended until: Amount of wall clock time specified by seconds has elapsed, OR A signal is caught by the process and the signal handler returns.
114
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 114 sleep Function 1.#include "apue.h" 2. 3.static void 4.sig_alrm(int signo) 5.{ 6. /* nothing to do, just returning wakes up sigsuspend() */ 7.}
115
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 115 sleep Function Solaris 9 Implements sleep using alarm Previously scheduled alarm is properly handled alarm(10) 3 wall clock seconds later sleep(5) SIGALRM received 2 seconds after waking from sleep alarm(6) 3 wall clock seconds later sleep(5) sleep returns in 3 seconds (not 5 seconds), return value of sleep is 2 (#unslept seconds) FreeBSD 5.2.1, Linux 2.4.22, Mac OS X 10.3 Implement sleep using nanosleep(2) (without signals, declared in Single UNIX Specification)
116
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 116 sleep Function 1.unsigned int 2.sleep(unsigned int nsecs) 3.{ 4. struct sigaction newact, oldact; 5. sigset_t newmask, oldmask, suspmask; 6. unsigned int unslept; 7. 8. /* set our handler, save previous information */ 9. newact.sa_handler = sig_alrm; 10. sigemptyset(&newact.sa_mask); 11. newact.sa_flags = 0; 12. sigaction(SIGALRM, &newact, &oldact);
117
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 117 sleep Function 1./* block SIGALRM and save current signal mask */ 2. sigemptyset(&newmask); 3. sigaddset(&newmask, SIGALRM); 4. sigprocmask(SIG_BLOCK, &newmask, &oldmask); 5. 6. alarm(nsecs); 7. 8. suspmask = oldmask; 9. /* make sure SIGALRM isn't blocked */ 10. sigdelset(&suspmask, SIGALRM); 11. /* wait for any signal to be caught */ 12. sigsuspend(&suspmask);
118
Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 118 sleep Function 1./* some signal has been caught, SIGALRM is now blocked */ 2. unslept = alarm(0); 3. /* reset previous action */ 4. sigaction(SIGALRM, &oldact, NULL); 5./* reset signal mask, which unblocks SIGALRM */ 6. sigprocmask(SIG_SETMASK, &oldmask, NULL); 7. return(unslept); 8.}
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.