歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

Linux信號編程實踐(一)

中斷

中斷是系統對於異步事件的響應, 進程執行代碼的過程中可以隨時被打斷,然後去執行異常處理程序;

計算機系統的中斷場景:中斷源發出中斷信號 -> CPU判斷中斷是否屏蔽以及保護現場 -> CPU(查詢中斷向量表, 找到中斷服務程序的入口地址)執行中斷處理程序 ->(處理完中斷之後) ->恢復現場,繼續執行原來的任務

 

中斷分類

硬件中斷(外部中斷)

外部中斷是指由外部設備通過硬件請求的方式產生的中斷,也稱為硬件中斷

軟件中斷(內部中斷)

內部中斷是由CPU運行程序錯誤或執行內部程序調用引起的一種中斷,也稱為軟件中斷(如:執行除0操作, 由用戶空間陷入內核空間等)。

 

信號

信號是UNIX/Linux系統響應某些狀況而產生的事件,進程在接收到信號時會采取相應的行動。信號一般是因為某些錯誤條件而產生的,比如內存段沖突、浮點處理器錯誤或者非法指令等;信號是在軟件層次上對中斷的一種模擬,所以通常把它稱為是軟中斷;

 

信號與中斷的相似點:

(1)采用了相同的異步通信方式;

(2)當檢測出有信號或中斷請求時,都暫停正在執行的程序而轉去執行相應的處理程序;

(3)都在處理完畢後返回到原來的斷點;

(4)對信號或中斷都可進行屏蔽。

 

信號與中斷的區別:

(1)中斷有優先級,而信號沒有優先級,所有的信號都是平等的;

(2)信號處理程序是在用戶態下運行的,而中斷處理程序是在核心態下運行;

(3)中斷響應是及時的,而信號響應通常都有較大的時間延遲。

Linux常用信號及其鍵值:

01 SIGHUP 掛起(hangup)

02 SIGINT 中斷,當用戶從鍵盤按^c鍵或^break鍵時

03 SIGQUIT 退出,當用戶從鍵盤按quit鍵時

04 SIGILL 非法指令

05 SIGTRAP 跟蹤陷阱(trace trap),啟動進程,跟蹤代碼的執行

06 SIGIOT IOT指令

07 SIGEMT EMT指令

08 SIGFPE 浮點運算溢出

09 SIGKILL 殺死、終止進程

10 SIGBUS 總線錯誤

11 SIGSEGV 段違例(segmentation violation),進程試圖去訪問其虛地址空間以外的位置

12 SIGSYS 系統調用中參數錯,如系統調用號非法

13 SIGPIPE 向某個非讀管道中寫入數據

14 SIGALRM 鬧鐘。當某進程希望在某時間後接收信號時發此信號

15 SIGTERM 軟件終止(software termination)

16 SIGUSR1 用戶自定義信號1

17 SIGUSR2 用戶自定義信號2

18 SIGCLD 某個子進程死

19 SIGPWR 電源故障

更加詳細的請參考 http://www.chengxuyuans.com/Linux/65677.html

進程對信號的響應可以分為一下幾種情況:

(1)忽略信號

不采取任何操作、有兩個信號不能被忽略:SIGKILL和SIGSTOP。

[為什麼進程不能忽略SIGKILL/SIGSTOP信號。(如果應用程序可以忽略這2個信號,系統管理無法殺死、暫停進程,無法對系統進行管理。)]

(2)捕獲並處理信號

內核中斷正在執行的代碼,轉去執行先前注冊過的處理程序。

(3)執行默認操作

默認操作通常是終止進程,這取決於被發送的信號。

信號的默認操作:通過 man 7 signal 查看

\

 

typedef void (*__sighandler_t) (int);
#define SIG_ERR ((__sighandler_t) -1)
#define SIG_DFL ((__sighandler_t) 0)
#define SIG_IGN ((__sighandler_t) 1)
__sighandler_t signal(int signum, __sighandler_t handler);

參數

signal是一個帶signum和handler兩個參數的函數,准備捕捉或屏蔽的信號由參數signum給出,接收到指定信號時將要調用的函數由handler給出handler這個函數必須有一個int類型的參數(即接收到的信號代碼),它本身的類型是void, handler也可以是下面兩個特殊值:

SIG_IGN 屏蔽該信號

SIG_DFL 恢復默認行為

並且返回的是上一次的信號處理函數,第一次的話則返回的是默認的處理函數。

 

void handler(int sig)
{
        printf("recv a sig=%d\n",sig);
}
int main()
{
        sig_t oldhandler;
        oldhandler=signal(SIGINT,handler);
        if(oldhandler==SIG_ERR)
                ERR_EXIT("signal error!");
        while(getchar()!='\n');
        if(signal(SIGINT,oldhandler)==SIG_ERR)// fanhuishangyicide signal
                ERR_EXIT("signal error!");
        while(1);
        return 0;
}

\
我們分析一下以上程序的結果:我們先樹勇signal注冊了一個SIGINT信號,每次使用ctrl+c時發出信號,執行handler函數,注意handler一定要有一個int形參。輸入回車跳出while循環,再次輸入ctrl+c時,這時候的handler是oldhandler(默認)所以會退出。

 

\

 

Copyright © Linux教程網 All Rights Reserved