SIGHUP信號與控制終端
UNIX中進程組織結構為 session (會話)包含一個前台進程組及一個或多個后台進程組,一個進程組包含多個進程。一個session可能會有一個session首進程,而一個session首進程可能會有一個控制終端。一個進程組可能會有一個進程組首進程。進程組首進程的進程ID與該進程組ID相等。這兒是可能會有,在一定情況之下是沒有的。與終端交互的進程是前台進程,否則便是后台進程。
SIGHUP會在以下3種情況下被發送給相應的進程:
1、終端關閉時,該信號被發送到session首進程以及作為job提交的進程(即用 & 符號提交的進程)
2、session首進程退出時,該信號被發送到該session中的前台進程組中的每一個進程
3、若父進程退出導致進程組成為孤兒進程組,且該進程組中有進程處於停止狀態(收到SIGSTOP或SIGTSTP信號),該信號會被發送到該進程組中的每一個進程。
系統對SIGHUP信號的默認處理是終止收到該信號的進程。所以若程序中沒有捕捉該信號,當收到該信號時,進程就會退出。
下面觀察幾種因終端關閉導致進程退出的情況,在這兒進程退出是因為收到了SIGHUP信號。login shell是session首進程。
首先寫一個測試程序,代碼如下:
#include <stdio.h>
#include
<signal.h>
char **
args;
void exithandle(int
sig)
{
printf("%s : sighup received ",args[1]);
}
int main(int argc,char **argv)
{
args = argv;
signal(SIGHUP,exithandle);
pause();
return 0;
}
程序中捕捉SIGHUP信號后打印一條信息,pause()使程序暫停。
編譯后的執行文件為sigtest。
1、命 令:sigtest front > tt.txt
操 作:關閉終端
結 果:tt.txt文件的內容為front : sighup received
原 因: sigtest是前台進程,終端關閉后,根據上面提到的第1種情況,login shell作為session首進程,會收到SIGHUP信號然后退出。根據第2種情況,sigtest作為前台進程,會收到login shell發出的SIGHUP信號。
2、命 令:sigtest back > tt.txt &
操 作:關閉終端
結 果:tt.txt文件的內容為 back : sighup received
原 因: sigtest是提交的job,根據上面提到的第1種情況,sigtest會收到SIGHUP信號。
3、命 令:寫一個shell,內容為[sigtest &],然后執行該shell
操 作:關閉終端
結 果:ps -ef | grep sigtest 會看到該進程還在,tt文件為空
原 因: 執行該shell時,sigtest作為job提交,然后該shell退出,致使sigtest變成了孤兒進程,不再是當前session的job了,因此sigtest即不是session首進程也不是job,不會收到SIGHUP。同時孤兒進程屬於后台進程,因此login shell退出后不會發送SIGHUP給sigtest,因為它只將該信號發送給前台進程。第3條說過若進程組變成孤兒進程組的時候,若有進程處於停止狀態,也會收到SIGHUP信號,但sigtest沒有處於停止狀態,所以不會收到SIGHUP信號。
4、命 令:nohup sigtest > tt
操 作:關閉終端
結 果:tt文件為空
原 因: nohup可以防止進程收到SIGHUP信號
至此,我們就清楚了何種情況下終端關閉后進程會退出,何種情況下不會退出。
要想終端關閉后進程不退出有以下幾種方法,均為通過shell的方式:
1、編寫shell,內容如下
trap "" SIGHUP #該句的作用是屏蔽SIGHUP信號,trap可以屏蔽很多信號
sigtest
2、nohup sigtest 可以直接在命令行執行,
若想做完該操作后繼續別的操作,可以 nohup sigtest &
3、編寫shell,內容如下
sigtest &
其實任何將進程變為孤兒進程的方式都可以,包括fork后父進程馬上退出。
signal(SIGHUP, SIG_IGN);
signal信號函數,第一個參數表示需要處理的信號值(SIGHUP),第二個參數為處理函數或者是一個表示,這里,SIG_IGN表示忽略SIGHUP那個注冊的信號。
SIGHUP
和控制台操作有關,當控制台被關閉時系統會向擁有控制台sessionID的所有進程發送HUP信號,默認HUP信號的action是
exit,如果遠程登陸啟動某個服務進程並在程序運行時關閉連接的話會導致服務進程退出,所以一般服務進程都會用nohup工具啟動或寫成一個 daemon。
、sighup與nohup
sighup(掛斷)信號:
在控制終端或者控制進程死亡時向關聯會話中的進程發出,默認進程對SIGHUP信號的處理是終止程序,所以我們在shell下建立的程序,在登錄退出連接斷開之后,會一並退出。
網上搜索到的解釋: 什么時候會發送 SIGHUP信號?當一個進程組成為孤兒進程組時,posix.1要求向孤兒進程組中處於停止狀態的進程發送SIGHUP(掛斷)信號,系統對於這種信號的默認處理是終止進程,然而如果無視這個信號或者另行處理的話,那么這個掛起進程仍可以繼續執行。
nohup命令:
故名思議就是忽略SIGHUP信號,一般搭配 & 一起使用,& 表示將此程序提交為后台作業或者說后台進程組。執行下面的命令
nohup bash -c "tail -f /var/log/messages | grep sys" &
1
nohup與&啟動的程序, 在終端還未關閉時,完全不像傳統的守護進程,因為其不是會話首進程且持有終端,只是其忽略了SIGHUP信號
從nohup源碼就可以看到,其實nohup只做了3件事情
dofile函數將輸出重定向到nohup.out文件
signal函數設置SIGHUP信號處理函數為SIG_IGN宏(指向sigignore函數),以此忽略SIG_HUP信號
execvp函數用新的程序替換當前進程的代碼段、數據段、堆段和棧段。
execvp 函數執行后,新程序(並沒有fork進程)會繼承一些調用進程屬性,比如:進程id、會話id,控制終端等
登錄連接斷開之后
在終端關閉后,nohup起到類似守護進程的效果,但是跟傳統的守護進程還是有區別的
nohup創建的進程工作目錄是你執行命令時所在的目錄
0 1 2 標准輸入 標准輸出 標准錯誤 指向nohup.out文件
nohup創建的進程組中,除首長進程的父進程id變為1之外,其余進程依然保留原來的會話id、進程組id、父進程id,都保持不變
網上搜索到的解釋: nohup命令可以將程序以忽略掛起信號的方式運行起來,被運行的程序的輸出信息將不會顯示到終端。
無論是否將 nohup 命令的輸出重定向到終端,輸出都將附加到當前目錄的 nohup.out 文件中。如果當前目錄的 nohup.out
文件不可寫,輸出重定向到$HOME/nohup.out文件中。如果沒有文件能創建或打開以用於追加,那么 command
參數指定的命令不可調用。如果標准錯誤是一個終端,那么把指定的命令寫給標准錯誤的所有輸出作為標准輸出重定向到相同的文件描述符。
linux——signal信號(SIGHUP、SIGINT、SIGQUIT、SIGILL、SIGTRAP、SIGABRT...........................)
https://blog.csdn.net/u014470361/article/details/83591513