linux程式設計下signal()函式

2puT發表於2016-07-22

當伺服器close一個連線時,若client端接著發資料。根據TCP協議的規定,會收到一個RST響應,client再往這個伺服器傳送資料時,系統會發出一個SIGPIPE訊號給程式,告訴程式這個連線已經斷開了,不要再寫了。根據訊號的預設處理規則SIGPIPE訊號的預設執行動作是terminate(終止、退出), 所以client會退出。
若不想客戶端退出可以把 SIGPIPE設為SIG_IGN
如:   signal(SIGPIPE,SIG_IGN);
這時SIGPIPE交給了系統處理。
伺服器採用了fork的話,要收集垃圾程式,防止僵死程式的產生,可以這樣處理:
signal(SIGCHLD,SIG_IGN); 交給系統init去回收。
這裡子程式就不會產生僵死程式了。

 

signal(SIGHUP, SIG_IGN);

signal訊號函式,第一個參數列示需要處理的訊號值(SIGHUP),第二個引數為處理函式或者是一個表示,這裡,SIG_IGN表示忽略SIGHUP那個註冊的訊號。

SIGHUP和控制檯操作有關,當控制檯被關閉時系統會向擁有控制檯sessionID的所有程式傳送HUP訊號,預設HUP訊號的action是exit,如果遠端登陸啟動某個服務程式並在程式執行時關閉連線的話會導致服務程式退出,所以一般服務程式都會用nohup工具啟動或寫成一個daemon。

unix中程式組織結構為 session 包含一個前臺程式組及一個或多個後臺程式組,一個程式組包含多個程式。

 

一個session可能會有一個session首程式,而一個session首程式可能會有一個控制終端。

 

一個程式組可能會有一個程式組首程式。程式組首程式的程式ID與該程式組ID相等。

 

這兒是可能會有,在一定情況之下是沒有的。

 

與終端互動的程式是前臺程式,否則便是後臺程式

 

SIGHUP會在以下3種情況下被髮送給相應的程式:

 

1、終端關閉時,該訊號被髮送到session首程式以及作為job提交的程式(即用 &符號提交的程式)

 

2、session首程式退出時,該訊號被髮送到該session中的前臺程式組中的每一個程式

 

3、若父程式退出導致程式組成為孤兒程式組,且該程式組中有程式處於停止狀態(收到SIGSTOP或SIGTSTP訊號),該訊號會被髮送到該程式組中的每一個程式。

 

系統對SIGHUP訊號的預設處理是終止收到該訊號的程式。所以若程式中沒有捕捉該訊號,當收到該訊號時,程式就會退出。

表標頭檔案#include<signal.h>   
功 能:
設定某一訊號的對應動作   
函式原型
void (*signal(int signum,void(* handler)(int)))(int);   
或者:typedef void(*sig_t) ( int );   sig_t signal(int signum,sig_thandler);   
引數說明:  
第一個引數signum指明瞭所要處理的訊號型別,它可以取除了SIGKILL和SIGSTOP外的任何一種訊號。  
第二個引數handler描述了與訊號關聯的動作,它可以取以下三種值:   
(1)一個返回值為正數的函式地址  此函式必須在signal()被呼叫前申明,handler中為這個函式的名字。當接收到一個型別為sig的訊號時,就執行handler所指定的函式。這個函式應有如下形式的定義:   intfunc(int sig);  sig是傳遞給它的唯一引數。執行了signal()呼叫後,程式只要接收到型別為sig的訊號,不管其正在執行程式的哪一部分,就立即執行func()函式。當func()函式執行結束後,控制權返回程式被中斷的那一點繼續執行。  
(2)SIGIGN   這個符號表示忽略該訊號,執行了相應的signal()呼叫後,程式會忽略型別為sig的訊號。   
(3)SIGDFL   這個符號表示恢復系統對訊號的預設處理。   
函式說明 :   signal()會依引數signum指定的訊號編號來設定該訊號的處理函式。當指定的訊號到達時就會跳轉到引數handler指定的函式執行。當一個訊號的訊號處理函式執行時,  如果程式又接收到了該訊號,該訊號會自動被儲存而不會中斷訊號處理函式的執行,直到訊號處理函式執行完畢再重新呼叫相應的處理函式。但是如果在訊號處理函式執行時程式收到了其它型別的訊號,該函式的執行就會被中斷。  
返回值: 返回先前的訊號處理函式指標,如果有錯誤則返回SIG_ERR(-1)。   
附加說明:在訊號發生跳轉到自定的handler處理函式執行後,系統會自動將此處理函式換回原來系統預設的處理方式,如果要改變此操作請改用sigaction()。  
下面的情況可以產生Signal:  
1. 按下CTRL+C產生SIGINT   
2. 硬體中斷,如除0,非法記憶體訪問(SIGSEV)等等   
3. Kill函式可以對程式傳送Signal   
4. Kill命令。實際上是對Kill函式的一個包裝   
5. 軟體中斷。如當AlarmClock超時(SIGURG),當Reader中止之後又向管道寫資料(SIGPIPE),等等   
 
2 Signals:

Signal Description
SIGABRT 由呼叫abort函式產生,程式非正常退出
SIGALRM 用alarm函式設定的timer超時或setitimer函式設定的intervaltimer超時
SIGBUS 某種特定的硬體異常,通常由記憶體訪問引起
SIGCANCEL 由Solaris Thread Library內部使用,通常不會使用
SIGCHLD 程式Terminate或Stop的時候,SIGCHLD會傳送給它的父程式。預設情況下該Signal會被忽略
SIGCONT 當被stop的程式恢復執行的時候,自動傳送
SIGEMT 和實現相關的硬體異常
SIGFPE 數學相關的異常,如被0除,浮點溢位,等等
SIGFREEZE Solaris專用,Hiberate或者Suspended時候傳送
SIGHUP 傳送給具有Terminal的ControllingProcess,當terminal被disconnect時候傳送
SIGILL 非法指令異常
SIGINFO BSD signal。由Status Key產生,通常是CTRL+T。傳送給所有ForegroundGroup的程式
SIGINT 由Interrupt Key產生,通常是CTRL+C或者DELETE。傳送給所有ForeGroundGroup的程式
SIGIO 非同步IO事件
SIGIOT 實現相關的硬體異常,一般對應SIGABRT
SIGKILL 無法處理和忽略。中止某個程式
SIGLWP 由Solaris Thread Libray內部使用
SIGPIPE 在reader中止之後寫Pipe的時候傳送
SIGPOLL 當某個事件傳送給Pollable Device的時候傳送
SIGPROF Setitimer指定的Profiling Interval Timer所產生
SIGPWR 和系統相關。和UPS相關。
SIGQUIT 輸入Quit Key的時候(CTRL+\)傳送給所有Foreground Group的程式
SIGSEGV 非法記憶體訪問
SIGSTKFLT Linux專用,數學協處理器的棧異常
SIGSTOP 中止程式。無法處理和忽略。
SIGSYS 非法系統呼叫
SIGTERM 請求中止程式,kill命令預設傳送
SIGTHAW Solaris專用,從Suspend恢復時候傳送
SIGTRAP 實現相關的硬體異常。一般是除錯異常
SIGTSTP Suspend Key,一般是Ctrl+Z。傳送給所有Foreground Group的程式
SIGTTIN 當Background Group的程式嘗試讀取Terminal的時候傳送
SIGTTOU 當Background Group的程式嘗試寫Terminal的時候傳送
SIGURG 當out-of-band data接收的時候可能傳送
SIGUSR1 使用者自定義signal 1
SIGUSR2 使用者自定義signal 2
SIGVTALRM setitimer函式設定的Virtual Interval Timer超時的時候
SIGWAITING Solaris Thread Library內部實現專用
SIGWINCH 當Terminal的視窗大小改變的時候,傳送給Foreground Group的所有程式
SIGXCPU 當CPU時間限制超時的時候
SIGXFSZ 程式超過檔案大小限制
SIGXRES Solaris專用,程式超過資源限制的時候傳送

  1、不要使用低階的或者STDIO.H的IO函式  2、不要使用對操作  3、不要進行系統呼叫   4、不是浮點訊號的時候不要用longjmp  5、singal函式是由ISO C定義的。因為ISOC不涉及多程式,程式組以及終端I/O等,所以他對訊號的定義非常含糊,以至於對UNIX系統而言幾乎毫無用處。  備註:因為singal的語義於現實有關,所以最好使用sigaction函式替代本函式。

相關文章