kill -l 查看所有信號程序員
前32個 unix經典信號算法
後32個稱爲實時信號(自定義信號)shell
kill能夠致使一個進程被終止網絡
90%的信號,默認都使進程終止併發
1.2 信號機制異步
信號的三大行爲和五種默認動做 函數
核心已轉儲 必定是Core 動做測試
SIGHUP 1 Term Hangup detected on controlling terminal or death of controlling process
SIGINT 2 Term Interrupt from keyboard
SIGQUIT 3 Core Quit from keyboard
SIGILL 4 Core Illegal Instruction
SIGABRT 6 Core Abort signal from abort(3)
SIGFPE 8 Core Floating point exception
SIGKILL 9 Term Kill signal
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 子進程結束給父進程發送一個SIGCHILD
SIGCONT 19,18,25 Cont Continue if stopped
SIGSTOP 17,19,23 Stop Stop process
SIGTSTP 18,20,24 Stop Stop typed at tty (ctrl+z)只能暫停終端前臺進程
SIGTTIN 21,21,26 Stop tty input for background process
SIGTTOU 22,22,27 Stop tty output for background processui
jobs spa
喚醒進程:fg(喚醒到前臺運行) bg(喚醒到後臺運行)
1.3 信號產生種類
kill(-1,9) -1是指給全部進程發送信號 執行這句話後致使計算機重啓
sig爲0時,用於檢測,特定爲pid進程是否存在,如不存在,返回-1。
1.4 信號產生緣由
1) SIGHUP:當用戶退出shell時,由該shell啓動的全部進程將收到這個信號,默認動做爲終止進程
2)SIGINT:當用戶按下了<Ctrl+C>組合鍵時,用戶終端向正在運行中的由該終端啓動的程序發出此信號。默認動做爲終止里程。3)SIGQUIT:當用戶按<ctrl+\>組合鍵時產生該信號,用戶終端向正在運行中的由該終端啓動的程序發出些信號。默認動做爲終止進程。
4)SIGILL:CPU檢測到某進程執行了非法指令。默認動做爲終止進程併產生core文件
5)SIGTRAP:該信號由斷點指令或其餘trap指令產生。默認動做爲終止里程併產生core文件。
6 ) SIGABRT:調用abort函數時產生該信號。默認動做爲終止進程併產生core文件。
7)SIGBUS:非法訪問內存地址,包括內存對齊出錯,默認動做爲終止進程併產生core文件。
8)SIGFPE:在發生致命的運算錯誤時發出。不只包括浮點運算錯誤,還包括溢出及除數爲0等全部的算法錯誤。默認動做爲終止進程併產生core文件。
9)SIGKILL:無條件終止進程。本信號不能被忽略,處理和阻塞。默認動做爲終止進程。它向系統管理員提供了能夠殺死任何進程的方法。
10)SIGUSE1:用戶定義的信號。即程序員能夠在程序中定義並使用該信號。默認動做爲終止進程。
11)SIGSEGV:指示進程進行了無效內存訪問。默認動做爲終止進程併產生core文件。
12)SIGUSR2:這是另一個用戶自定義信號,程序員能夠在程序中定義並使用該信號。默認動做爲終止進程。1
13)SIGPIPE:Broken pipe向一個沒有讀端的管道寫數據。默認動做爲終止進程。
14) SIGALRM:定時器超時,超時的時間由系統調用alarm設置。默認動做爲終止進程。
15)SIGTERM:程序結束信號,與SIGKILL不一樣的是,該信號能夠被阻塞和終止。一般用來要示程序正常退出。執行shell命令Kill時,缺省產生這個信號。默認動做爲終止進程。
16)SIGCHLD:子進程結束時,父進程會收到這個信號。默認動做爲忽略這個信號。
17)SIGCONT:中止進程的執行。信號不能被忽略,處理和阻塞。默認動做爲終止進程。
18)SIGTTIN:後臺進程讀終端控制檯。默認動做爲暫停進程。
19)SIGTSTP:中止進程的運行。按下<ctrl+z>組合鍵時發出這個信號。默認動做爲暫停進程。
21)SIGTTOU:該信號相似於SIGTTIN,在後臺進程要向終端輸出數據時發生。默認動做爲暫停進程。
22)SIGURG:套接字上有緊急數據時,向當前正在運行的進程發出些信號,報告有緊急數據到達。如網絡帶外數據到達,默認動做爲忽略該信號。
23)SIGXFSZ:進程執行時間超過了分配給該進程的CPU時間,系統產生該信號併發送給該進程。默認動做爲終止進程。
24)SIGXFSZ:超過文件的最大長度設置。默認動做爲終止進程。
25)SIGVTALRM:虛擬時鐘超時時產生該信號。相似於SIGALRM,可是該信號只計算該進程佔用CPU的使用時間。默認動做爲終止進程。
26)SGIPROF:相似於SIGVTALRM,它不公包括該進程佔用CPU時間還包括執行系統調用時間。默認動做爲終止進程。
27)SIGWINCH:窗口變化大小時發出。默認動做爲忽略該信號。
28)SIGIO:此信號向進程指示發出了一個異步IO事件。默認動做爲忽略。
29)SIGPWR:關機。默認動做爲終止進程。
30)SIGSYS:無效的系統調用。默認動做爲終止進程併產生core文件。
31)SIGRTMIN~(64)SIGRTMAX:LINUX的實時信號,它們沒有固定的含義(能夠由用戶自定義)。全部的實時信號的默認動做都爲終止進程。
1.4 信號集處理函數
sigset_t爲信號集,可sizeof(sigset_t)察看
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(const sigset_t *set, int signo)
unix經典信號不支持排隊(最多有一個)
例:利用捕捉函數測試,當咱們同時按不少次ctrl + c 時,只執行兩次
當第一個信號a(編號爲2)發來時,經過未決信號集,未決信號集置1,而後經過阻塞信號集,到達Handler,未決信號集置0,執行函數,在執行過程當中,系統將阻塞信號集的2號信號置1,此時,還有新的信號b(2)經過未決信號集,而後未決信號集置1 ,但此時,阻塞信號集2號信號也爲1,因此信號b就在未決信號和阻塞信號集之間,其他到來的信號,因爲未決信號集2號信號爲1,都被忽略,當函數執行完畢,則阻塞信號集置0,信號b經過,因此只執行兩次函數。
測試代碼:
#include <stdio.h> #include <unistd.h> #include <signal.h> void sig_func(int n) { int flag = 3; for(int i = 0; i < 3;i++) { printf("---flag:%d-----\n",flag); flag--; sleep(1); } } int main() { struct sigaction act,oldact; act.sa_handler = sig_func; act.sa_flags = 0; sigemptyset(&act.sa_mask); sigaction(SIGINT,&act,&oldact); while(1); }
結果:
alarm返回沒定時夠的秒數(定時10s可是在過了2s後,程序被終端則返回8s)
時序競態:原子功能,信號之間用全局資源用可重入函數
測試代碼:
#include <stdio.h> #include <unistd.h> #include <signal.h> void alm(int n) {} unsigned int mysleep(unsigned int seconds) { //由於時間資源的競爭,致使程序引起災難性後果,時序竟態 int reval; sigset_t set,oldset; sigemptyset(&set); sigaddset(&set,SIGALRM); sigprocmask(SIG_BLOCK,&set,&oldset); sigemptyset(&oldset); signal(SIGALRM,alm); reval = alarm(seconds); if(reval == -1) perror("Alarm call Failed:"); //pause(); sigsuspend(&oldset); } int main() { while(1) { printf("Two seconds..\n"); mysleep(2); } }
用pause函數存在的問題:當計時器開始計數,但時間片沒有了,去執行其餘進程,過程當中發回SIGALRM,當時間片輪轉回來時,會先處理信號,而後再執行pause(),這樣線程就會永遠不被喚醒。
int pause(void)
使調用進程掛起,直到有信號遞達,若是遞達信號是忽略,則繼續掛起
int sigsuspend(const sigset_t *mask) 1.以經過指定mask來臨時解除對某個信號的屏蔽, 2.而後掛起等待, 3.當被信號喚醒sigsuspend返回時,進程的信號屏蔽字恢復爲原來的值