signal定義
unix類系統中,信號是進程間通訊的方式,linux系統中定義的Signal常量及其說明可以在/usr/include/bits/signum.h的頭文件中,定義如下:
/* Signals. */ #define SIGHUP 1 /* Hangup (POSIX). */ #define SIGINT 2 /* Interrupt (ANSI). */ #define SIGQUIT 3 /* Quit (POSIX). */ #define SIGILL 4 /* Illegal instruction (ANSI). */ #define SIGTRAP 5 /* Trace trap (POSIX). */ #define SIGABRT 6 /* Abort (ANSI). */ #define SIGIOT 6 /* IOT trap (4.2 BSD). */ #define SIGBUS 7 /* BUS error (4.2 BSD). */ #define SIGFPE 8 /* Floating-point exception (ANSI). */ #define SIGKILL 9 /* Kill, unblockable (POSIX). */ #define SIGUSR1 10 /* User-defined signal 1 (POSIX). */ #define SIGSEGV 11 /* Segmentation violation (ANSI). */ #define SIGUSR2 12 /* User-defined signal 2 (POSIX). */ #define SIGPIPE 13 /* Broken pipe (POSIX). */ #define SIGALRM 14 /* Alarm clock (POSIX). */ #define SIGTERM 15 /* Termination (ANSI). */ #define SIGSTKFLT 16 /* Stack fault. */ #define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ #define SIGCHLD 17 /* Child status has changed (POSIX). */ #define SIGCONT 18 /* Continue (POSIX). */ #define SIGSTOP 19 /* Stop, unblockable (POSIX). */ #define SIGTSTP 20 /* Keyboard stop (POSIX). */ #define SIGTTIN 21 /* Background read from tty (POSIX). */ #define SIGTTOU 22 /* Background write to tty (POSIX). */ #define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */ #define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */ #define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */ #define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */ #define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */ #define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */ #define SIGPOLL SIGIO /* Pollable event occurred (System V). */ #define SIGIO 29 /* I/O now possible (4.2 BSD). */ #define SIGPWR 30 /* Power failure restart (System V). */ #define SIGSYS 31 /* Bad system call. */ #define SIGUNUSED 31
signal捕獲
通過signal函數可以自定義對信號的處理方法,定義如下:
signal(int signum, void (signalHandler*)(int)); //自定義信號處理 signal(int signum, SIG_IGN); //忽略信號
示例
#include <iostream> #include <signal.h> #include <unistd.h> /** * 處理signal信號 **/ void signalHandler(int signal) { std::cout << "signalHandler get signlal " << signal << std::endl; } int main(int argc, char* argv[]) { /** * ctrl + c **/ signal(SIGINT, signalHandler); /** * ctrl + \ **/ signal(SIGQUIT, signalHandler); while(true) { sleep(1); } }
在一個運行的程序的控制終端鍵入特定的組合鍵可以向它發送某些信號:
Ctrl-C發送INT信號(SIGINT);默認情況下,這會導致進程終止。
Ctrl-Z發送TSTP信號(SIGTSTP);默認情況下,這會導致進程掛起。
Ctrl-\發送QUIT信號(SIGQUIT);默認情況下,這會導致進程終止並且將內存中的信息轉儲到硬盤(核心轉儲)。
(這些組合鍵可以通過stty命令來修改。)
運行時輸入:ctrl+c和ctrl+\
無法捕獲的信號信號SIGKILL和SIGSTOP
所有的信號中,只有信號SIGKILL和SIGSTOP無法被捕捉到,當SIGSTOP被程序接收到時,默認會暫停執行,如果需要繼續執行發送SIGCONT信號,當SIGKILL接收到時會直接關閉,不能執行任何清理,下面以一個每秒寫入一次文件的程序做示例。
#include <iostream> #include <signal.h> #include <unistd.h> #include <fcntl.h> #include <time.h> #include <string.h> /** * 處理signal信號 **/ void signalHandler(int signal) { std::cout << "signalHandler get signlal " << signal << std::endl; } int main(int argc, char* argv[]) { /** * kill -9 **/ signal(SIGKILL, signalHandler); /** * ctrl + z **/ signal(SIGSTOP, signalHandler); int fd = open("/home/course/unix/output.data", O_RDWR | O_TRUNC | O_CREAT); if(fd == -1) { std::perror("/home/course/unix/output.data"); exit(1); } while(true) { sleep(1); write(fd, "abc\n", 4); } }
執行程序後,tail查看output.data文件一直在追加寫入
發送SIGSTOP
kill -SIGSTOP 12266
此時的文件讀寫暫停,程序暫停運行了,如果需要程序繼續運行,發送SIGCONT信號,如下,又開始繼續追加
發送SIGKILL殺掉進程
在以上兩個SIGKILL和SIGSTOP信號發送過程中,進程都無法捕獲到對應的信號。
參考:
https://major.io/2009/06/15/two-great-signals-sigstop-and-sigcont/
https://serverfault.com/questions/319684/what-s-s1-t-r-mean-in-ps-ax-ps-list