linux下的SIGHUP系統信號


對於SIGHUP信號的介紹

  在介紹SIGHUP信號之前,先來了解兩個概念:進程組和會話。

進程組
  進程組就是一系列相互關聯的進程集合,系統中的每一個進程也必須從屬於某一個進程組;每個進程組中都會有一個唯一的 ID(process group id),簡稱 PGID;PGID 一般等同於進程組的創建進程的 Process ID,而這個進進程一般也會被稱為進程組先導(process group leader),同一進程組中除了進程組先導外的其他進程都是其子進程;
  進程組的存在,方便了系統對多個相關進程執行某些統一的操作,例如,我們可以一次性發送一個信號量給同一進程組中的所有進程。

會話
  會話(session)是一個若干進程組的集合,同樣的,系統中每一個進程組也都必須從屬於某一個會話;一個會話只擁有最多一個控制終端(也可以沒有),該終端為會話中所有進程組中的進程所共用。一個會話中前台進程組只會有一個,只有其中的進程才可以和控制終端進行交互;除了前台進程組外的進程組,都是后台進程組;和進程組先導類似,會話中也有會話先導(session leader)的概念,用來表示建立起到控制終端連接的進程。在擁有控制終端的會話中,session leader 也被稱為控制進程(controlling process),一般來說控制進程也就是登入系統的 shell 進程(login shell);
  
  執行睡眠后台進程sleep 50 & 之后,通過 ps命令查看該進程及shell信息如上圖:

PPID 指父進程 id;PID 指進程 id;PGID 指進程組 id
SID 指會話 id;TTY 指會話的控制終端設備;COMMAND 指進程所執行的命令
TPGID 指前台進程組的 PGID。

SIGHUP信號的觸發及默認處理
  在對會話的概念有所了解之后,我們現在開始正式介紹一下SIGHUP信號,SIGHUP 信號在用戶終端連接(正常或非正常)結束時發出, 通常是在終端的控制進程結束時, 通知同一session內的各個作業, 這時它們與控制終端不再關聯. 系統對SIGHUP信號的默認處理是終止收到該信號的進程。所以若程序中沒有捕捉該信號,當收到該信號時,進程就會退出。
  
SIGHUP會在以下3種情況下被發送給相應的進程:
  1、終端關閉時,該信號被發送到session首進程以及作為job提交的進程(即用 & 符號提交的進程);
  2、session首進程退出時,該信號被發送到該session中的前台進程組中的每一個進程;
   3、若父進程退出導致進程組成為孤兒進程組,且該進程組中有進程處於停止狀態(收到SIGSTOP或SIGTSTP信號),該信號會被發送到該進程組中的每一個進程。
  
  例如:在我們登錄Linux時,系統會分配給登錄用戶一個終端(Session)。在這個終端運行的所有程序,包括前台進程組和后台進程組,一般都屬於這個 Session。當用戶退出Linux登錄時,前台進程組和后台有對終端輸出的進程將會收到SIGHUP信號。這個信號的默認操作為終止進程,因此前台進 程組和后台有終端輸出的進程就會中止。

此外,對於與終端脫離關系的守護進程,這個信號用於通知它重新讀取配置文件。 比如xinetd超級服務程序。
  當xinetd程序在接收到SIGHUP信號之后調用hard_reconfig函數,它將循環讀取/etc/xinetd.d/目錄下的每個子配置文件,並檢測其變化。如果某個正在運行的子服務的配置文件被修改以停止服務,則xinetd主進程講給該子服務進程發送SIGTERM信號來結束它。如果某個子服務的配置文件被修改以開啟服務,則xinetd將創建新的socket並將其綁定到該服務對應的端口上。

SIGPIPE
  在網絡編程中,SIGPIPE這個信號是很常見的。當往一個寫端關閉的管道或socket連接中連續寫入數據時會引發SIGPIPE信號,引發SIGPIPE信號的寫操作將設置errno為EPIPE。在TCP通信中,當通信的雙方中的一方close一個連接時,若另一方接着發數據,根據TCP協議的規定,會收到一個RST響應報文,若再往這個服務器發送數據時,系統會發出一個SIGPIPE信號給進程,告訴進程這個連接已經斷開了,不能再寫入數據。

  此外,因為SIGPIPE信號的默認行為是結束進程,而我們絕對不希望因為寫操作的錯誤而導致程序退出,尤其是作為服務器程序來說就更惡劣了。所以我們應該對這種信號加以處理,在這里,介紹兩種處理SIGPIPE信號的方式:
  1 、給SIGPIPE設置SIG_IGN信號處理函數,忽略該信號:

signal(SIGPIPE, SIG_IGN);
1
  前文說過,引發SIGPIPE信號的寫操作將設置errno為EPIPE,。所以,第二次往關閉的socket中寫入數據時, 會返回-1, 同時errno置為EPIPE. 這樣,便能知道對端已經關閉,然后進行相應處理,而不會導致整個進程退出.
  2、使用send函數的MSG_NOSIGNAL 標志來禁止寫操作觸發SIGPIPE信號。

send(sockfd , buf , size , MSG_NOSIGNAL);
1
   同樣,我們可以根據send函數反饋的errno來判斷socket的讀端是否已經關閉。
   此外,我們也可以通過IO復用函數來檢測管道和socket連接的讀端是否已經關閉。以POLL為例,當socket連接被對方關閉時,socket上的POLLRDHUP事件將被觸發。

SIGURG
  在介紹SIGURG信號之前,先來說說什么是帶外數據。

帶外數據
  帶外數據用於迅速告知對方本端發生的重要的事件。它比普通的數據(帶內數據)擁有更高的優先級,不論發送緩沖區中是否有排隊等待發送的數據,它總是被立即發送。帶外數據的傳輸可以使用一條獨立的傳輸層連接,也可以映射到傳輸普通數據的連接中。實際應用中,帶外數據是使用很少見,有,telnet和ftp等遠程非活躍程序。
  UDP沒有沒有實現帶外數據傳輸,TCP也沒有真正的帶外數據。不過TCP利用頭部的緊急指針標志和緊急指針,為應用程序提供了一種緊急方式,含義和帶外數據類似。TCP的緊急方式利用傳輸普通數據的連接來傳輸緊急數據。

SIGURG信號的作用
  內核通知應用程序帶外數據到達的方式有兩種:一種就是利用IO復用技術的系統調用(如select)在接受到帶外數據時將返回,並向應用程序報告socket上的異常事件。
  另一種方法就是使用SIGURG信號。

若對服務器同時處理普通數據和帶外數據感興趣的話可以參考示例程序。

https://blog.csdn.net/z_ryan/article/details/80952498?utm_source=blogxgwz6

在介紹在網絡編程中幾個密切相關的函數:SIGPIPE,SIGURG、、、、、、

名稱      默認動作            說明

  SIGHUP      終止進程      終端線路掛斷

  SIGINT    終止進程      中斷進程

  SIGQUIT   建立CORE文件  終止進程,並且生成core文件

  SIGILL    建立CORE文件        非法指令

  SIGTRAP   建立CORE文件        跟蹤自陷

  SIGBUS    建立CORE文件        總線錯誤

  SIGSEGV   建立CORE文件        段非法錯誤

  SIGFPE    建立CORE文件        浮點異常

  SIGIOT    建立CORE文件        執行I/O自陷

  SIGKILL   終止進程      殺死進程

  SIGPIPE   終止進程      向一個沒有讀進程的管道寫數據

  SIGALarm  終止進程      計時器到時

  SIGTERM   終止進程      軟件終止信號

  SIGSTOP   停止進程      非終端來的停止信號

  SIGTSTP   停止進程      終端來的停止信號

  SIGCONT   忽略信號      繼續執行一個停止的進程

  SIGURG    忽略信號      I/O緊急信號

  SIGIO     忽略信號      描述符上可以進行I/O

  SIGCHLD   忽略信號      當子進程停止或退出時通知父進程

  SIGTTOU   停止進程      后台進程寫終端

  SIGTTIN   停止進程      后台進程讀終端

  SIGXGPU   終止進程      CPU時限超時

  SIGXFSZ   終止進程      文件長度過長

  SIGWINCH  忽略信號      窗口大小發生變化

  SIGPROF   終止進程      統計分布圖用計時器到時

  SIGUSR1   終止進程      用戶定義信號1

  SIGUSR2   終止進程      用戶定義信號2

  SIGVTALRM 終止進程      虛擬計時器到時

  1) SIGHUP 本信號在用戶終端連接(正常或非正常)結束時發出, 通常是在終端的控制進程結束時, 通知同一session內的各個作業, 這時它們與控制終端不再關聯.

  2) SIGINT 程序終止(interrupt)信號, 在用戶鍵入INTR字符(通常是Ctrl-C)時發出

  3) SIGQUIT 和SIGINT類似, 但由QUIT字符(通常是Ctrl-\)來控制. 進程在因收到SIGQUIT退出時會產生core文件, 在這個意義上類似於一個程序錯誤信號.

  4) SIGILL 執行了非法指令. 通常是因為可執行文件本身出現錯誤, 或者試圖執行數據段. 堆棧溢出時也有可能產生這個信號.

  5) SIGTRAP 由斷點指令或其它trap指令產生. 由debugger使用.

  6) SIGABRT 程序自己發現錯誤並調用abort時產生.

  7) SIGIOT 在PDP-11上由iot指令產生, 在其它機器上和SIGABRT一樣.

  8) SIGBUS 非法地址, 包括內存地址對齊(alignment)出錯. eg: 訪問一個四個字長的整數, 但其地址不是4的倍數.

  9) SIGFPE 在發生致命的算術運算錯誤時發出. 不僅包括浮點運算錯誤, 還包括溢出及除數為0等其它所有的算術的錯誤.

  10) SIGKILL 用來立即結束程序的運行. 本信號不能被阻塞, 處理和忽略.

  11) SIGUSR1 留給用戶使用

  12) SIGSEGV 試圖訪問未分配給自己的內存, 或試圖往沒有寫權限的內存地址寫數據.

  13) SIGUSR2 留給用戶使用

  14) SIGPIPE Broken pipe

  15) SIGALRM 時鍾定時信號, 計算的是實際的時間或時鍾時間. alarm函數使用該信號.

  16) SIGTERM 程序結束(terminate)信號, 與SIGKILL不同的是該信號可以被阻塞和處理. 通常用來要求程序自己正常退出. shell命令kill缺省產生這個信號.

  17) SIGCHLD 子進程結束時, 父進程會收到這個信號.

  18) SIGCONT 讓一個停止(stopped)的進程繼續執行. 本信號不能被阻塞. 可以用一個handler來讓程序在由stopped狀態變為繼續執行時完成特定的工作. 例如, 重新顯示提示符.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM