signal 通知 process 事件發生,或稱為軟體中斷,和硬體中斷一樣中斷程式正常流程。signal 來源可能是
- 另一個 process,可作為同步機制或 IPC 原型。
- 自己
- kernel
- hardare exception,如不對的機器指令、除以 0、存取非法位址。
- 終端機特殊字元,如中斷字元 Ctrl-C、suspend 字元 Ctrl-Z。
- software event,收到 file 輸入、視窗改變大小、timer 時間到、超出 CPU 使用時間、child process 結束。
每個 signal 用 1 開始的小數字表示,在 signal.h 名稱定義為 SIGxxx。signal 分成兩類,一是傳統的標準 signal,在 Linux 是 1~31。另一種 realtime signal。
signal 在排程準備要執行時處理,如果已經執行中則馬上處理。signal 從產生 (generated) 到送達 (delivered) 之間是 pending。process 可設遮蔽 (mask) 來 block 特定 signal 而讓其產生後一直 pending,直到 unblock。每個 thread 有自己的 signal mask,pthread_sigmask() 設定 thread 哪些 signal
blocked。傳統 single-threaded 應用,sigprocmask() 可用來設定 signal mask (用在
multi-thread 會怎樣?)。fork() 繼承 signal mask,execve() 保留 signal mask
(繼承和保留有何不同?)。
signal 送達時執行下列預設「動作」(Action) 之一:
- Ign:忽略,process 不會發現。
- Term:process 結束 (killed),是 abnormal process termination,有別於 exit() 的 normal process termination。
- Core:process core dump 並結束。core dump 包含 process 的 virtual memory image,可作為除錯用。
- Stop:process 暫停。
- Cont:暫停的 process 繼續。
Signal | 值 | 動作 (預設)
| 說明 |
SIGHUP | 1 | Term | kill. 控制終端機偵測到 Hangup 或控制行程 death。 |
SIGINT | 2 | Term | 中斷字元 Ctrl-C 產生。
|
SIGQUIT | 3 | Core | Quit from keyboard |
SIGILL | 4 | Core | Illegal Instruction |
SIGABRT | 6 | Core | abort() 產生,用來產生 core dump。
|
SIGFPE | 8 | Core | Floating point exception |
SIGKILL | 9 | Term | Kill signal (無法 caught、blocked、或 ignored)
|
SIGSEGV | 11 | Core | Invalid memory reference |
SIGPIPE | 13 | Term | Broken pipe: write to pipe with no readers |
SIGALRM | 14 | Term | Timer signal from alarm(2) |
SIGTERM | 15 | Term | Termination signal |
SIGUSR1 | 30,10,16 | Term | User-defined signal 1 |
SIGUSR2 | 31,12,17 | Term | User-defined signal 2 |
SIGCHLD | 20,17,18 | Ign | Child stopped or terminated |
SIGCONT | 19,18,25 | Cont | Continue if stopped |
SIGSTOP | 17,19,23 | Stop | Stop process (無法 caught、blocked、或 ignored) |
SIGTSTP | 18,20,24 | Stop | Stop typed at terminal |
SIGTTIN | 21,21,26 | Stop | Terminal input for background process |
SIGTTOU | 22,22,27 | Stop | Terminal output for background process |
可用 sigaction() 或 signal() 改變動作,或稱為設定 disposition,可選擇 1) 回復預設動作、2) 忽略、或 3) 執行 signal handler。執行 signal handler 時,稱為 caught。如果想要 signal handler 結束 process,可執行 exit()。如果想要 signal handler core dump 後結束 process,可執行 abort()。signal 的動作是 process 屬性,其下 thread 共用。fork() 繼承。execve() 時,除了忽略的 signal 外,其它回復預設動作。
/proc/PID/status 包含 hex 表示的 bit-mask fields 查看 signal 狀態
SigPnd:per-thread pending
ShdPnd:process-wide pending
SigBlk:blocked
SigIgn:ignored
SigCgt:caught
signal 可以是 process-directed 或 thread-directed。process-directed 的 signal 是 targeted 整個 process,來自 kernel other than a hardware exception,或 kill() 或 sigqueue()。thread-directed 的 signal 是 targeted 特定 thread,這些是來自 hardware exception (如 invalid memory access 產生 SIGSEGV,math error 產生 SIGFPE) 或使用 tgkill() 或 pthread_kill()。process-directed signal 任意由一個沒 block 的 thread 處理。thread 可 sigpending() 取得目前 pending 的 signal,包含 process-directed 和給自己 thread-directed。fork() 一開始 pending signal set 是空的,execve() 保留 pending signal set。
standard signal 各自只有一個,沒有特定處理順序。pending 時再發生也只有一個。
signal handler 預設使用 the normal process stack (是指 thread stack?process 有 stack?),可用 sigaltstack() 改用不同的 stack。
送 signal
- raise():送 signal 給自己 thread。
- kill():送 signal 給指定的 process、指定的 process group、或所有 processe。
- killpg():送 signal 給指定的 process group。
- pthread_kill():送 signal 給 process 內指定的 thread。
- tgkill():實作 pthread_kill() 的系統呼叫。
- sigqueue():送 real-time signal 及 accompanying data 給指定的 process。
等 signal
- 系統呼叫 pause():暫停執行直到補抓到任何 signal。
- 系統呼叫 sigsuspend():暫時改變 signal mask 並暫停執行直到補抓到任何 unmasked 的 signal。
- 系統呼叫 sigwaitinfo()、sigtimedwait()、和 sigwait():暫停執行直到補抓到指定的 signal 並回傳 signal 資訊。
- 系統呼叫 signalfd():回傳 file descriptor 用來讀有關 signal 的資訊,read() 後等候指定的 signal 並得到描述 signal 的資料結構。
可以用 pthread_sigmask() 或 sigprocmask() 設 mask 來讓 signal pending 進不來,直到 unmask。用 sigpending() 查看 pending siganl。
程序管理
INT (Ctrl-C)
TERM (kill 預設)
WINCH
SEGV
EXIT
USR1
USR2
ALARM
HUP
Real-time signals:範圍定義在 SIGRTMIN 和 SIGRTMAX 之間,Linux kernel 支援 32 到 64,但 glibc POSIX thread 實作只用 2 (NPTL) 或 3 (LinuxThreads) 個。real-time signal 運用由應用程式定義,沒有事先定義,預設動作是 Term。real-time signal 的不同...
參考
- man 7 signal
- http://www.gnu.org/software/libc/manual/html_node/Signal-Handling.html
- busybox ping
- busybox dhcpc:用 SIGUSR1 來更新 IP 租約, 用 SIGUSR2 來釋出 IP 租約。
- TLPI §20.1