2021-05-12 14:32:11
關於 Linux 信號詳解
信號的基本概念
每個信號都有一個編號和一個宏定義名稱 ,這些宏定義可以在 signal.h 中找到。
對信號的三種處理方式
- 忽略此信號:大多數信號都可使用這種方式進行處理,但有兩種信號卻決不能被忽略。它們是:SIGKILL和SIGSTOP。這兩種信號不能被忽略的,原因是:它們向超級使用者提供一種使進程終止或停止的可靠方法。另外,如果忽略某些由硬體異常產生的信號(例如非法儲存存取或除以0),則進程的行為是示定義的。
- 直接執行進程對於該信號的預設動作 :對大多數信號的系統預設動作是終止該進程。
- 捕捉信號:執行自定義動作(使用signal函數),為了做到這一點要通知核心在某種信號發生時,呼叫一個使用者函數handler。在使用者函數中,可執行使用者希望對這種事件進行的處理。注意,不能捕捉SIGKILL和SIGSTOP信號。
1
2
3
|
#include <signal.h> typedef void ( *sighandler_t)( int ); sighandler_t signal ( int signum, sighandler_t handler); |
signal函數的作用:給某一個進程的某一個特定信號(標號為signum)註冊一個相應的處理常式,即對該信號的預設處理動作進行修改,修改為handler函數所指向的方式。
- 第一個引數是信號的標號
- 第二個引數,sighandler_t是一個typedef來的,原型是void (*)(int)函數指標,int的引數會被設定成signum
舉個程式碼例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include<stdio.h> #include<signal.h> void handler( int sig) { printf ( "get a sig,num is %dn" ,sig); } int main() { signal (2,handler); while (1) { sleep(1); printf ( "hellon" ); } return 0; } |
修改了2號信號(Ctrl-c)的預設處理動作為handler函數的內容,則當該程式在前台執行時,鍵入Ctrl-c後不會執行它的預設處理動作(終止該進程)
信號的處理過程:
進程收到一個信號後不會被立即處理,而是在恰當 時機進行處理!什麼是適當的時候呢?比如說中斷返回的時候,或者核心態返回使用者態的時候(這個情況出現的比較多)。
信號不一定會被立即處理,作業系統不會為了處理一個信號而把當前正在執行的進程掛起(切換進程),掛起(進程切換)的話消耗太大了,如果不是緊急信號,是不會立即處理的。作業系統多選擇在核心態切換回使用者態的時候處理信號,這樣就利用兩者的切換來處理了(不用單獨進行進程切換以免浪費時間)。
總歸是不能避免的,因為很有可能在睡眠的進程就接收到信號,作業系統肯定不願意切換當前正在執行的進程,於是就得把信號儲存在進程唯一的PCB(task_struct)當中。
產生信號的條件
信號的產生
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/************************************************************************* > File Name: test .c > Author:Lynn-Zhang > Mail: iynu17@yeah.net > Created Time: Fri 15 Jul 2016 03:03:57 PM CST ************************************************************************/ #include<stdio.h> int main() { printf ( "get pid :%d circle ...n" ,getpid()); while (1); return 0; } |
kill命令是呼叫kill函數實現的。kill函數可以給一個指定的進程傳送指定信號。
raise函數可 以給當前進程傳送指定的信號 (自己給自己發信號 )
1
2
3
|
#include<signal.h> int kill(pid_t pid, int signo); int raise ( int signo); |
1
2
|
#include<stdlib.h> void abort ( void ); |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/************************************************************************* > File Name: alarm.c > Author:Lynn-Zhang > Mail: iynu17@yeah.net > Created Time: Fri 15 Jul 2016 08:52:02 PM CST ************************************************************************/ #include<stdio.h> int main() { int count=0; alarm(1); while (1) { printf ( "%dn" ,count); count++; } return 0; } |
通過實現以上程式碼,呼叫alarm函數可以設定一個鬧鐘,告訴核心在seconds秒之後給當前進程發SIGALRM信號, 該信號的預設處理動作是終止當前進程。
該程式會在1秒鐘之內不停地數數,並列印計數器,1秒鐘到了就被SIGALRM信號終止。由於電腦設定等的不同,每台電腦一秒鐘之內計數值是不同的一般是不同的。
1
2
|
#include <unistd.h> unsigned int alarm(unsigned int seconds); |
alarm函數的返回值是0或上次設定鬧鐘剩餘的時間。
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2016-08/134303p2.htm
相關文章