http://en.wikipedia.org/wiki/Category:Unix_signals 1.SIGHUP信號 UNIX中進(jìn)程組織結(jié)構(gòu)為 session (會話)包含一個前臺進(jìn)程組及一個或多個后臺進(jìn)程組,一個進(jìn)程組包含多個進(jìn)程。一個session可能會有一個session首進(jìn)程,而一個session首進(jìn)程可能會有一個控制終端。一個進(jìn)程組可能會有一個進(jìn)程組首進(jìn)程。進(jìn)程組首進(jìn)程的進(jìn)程ID與該進(jìn)程組ID相等。這兒是可能會有,在一定情況之下是沒有的。與終端交互的進(jìn)程是前臺進(jìn)程,否則便是后臺進(jìn)程。
SIGHUP會在以下3種情況下被發(fā)送給相應(yīng)的進(jìn)程:
1、終端關(guān)閉時,該信號被發(fā)送到session首進(jìn)程以及作為job提交的進(jìn)程(即用 & 符號提交的進(jìn)程)
2、session首進(jìn)程退出時,該信號被發(fā)送到該session中的前臺進(jìn)程組中的每一個進(jìn)程
3、若父進(jìn)程退出導(dǎo)致進(jìn)程組成為孤兒進(jìn)程組,且該進(jìn)程組中有進(jìn)程處于停止?fàn)顟B(tài)(收到SIGSTOP或SIGTSTP信號),該信號會被發(fā)送到該進(jìn)程組中的每一個進(jìn)程。
系統(tǒng)對SIGHUP信號的默認(rèn)處理是終止收到該信號的進(jìn)程。所以若程序中沒有捕捉該信號,當(dāng)收到該信號時,進(jìn)程就會退出。
下面觀察幾種因終端關(guān)閉導(dǎo)致進(jìn)程退出的情況,在這兒進(jìn)程退出是因?yàn)槭盏搅薙IGHUP信號。login shell是session首進(jìn)程。
首先寫一個測試程序,代碼如下:
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() 程序中捕捉SIGHUP信號后打印一條信息,pause()使程序暫停。
編譯后的執(zhí)行文件為sigtest。
1、命 令:sigtest front > tt.txt
操 作:關(guān)閉終端
結(jié) 果:tt.txt文件的內(nèi)容為front : sighup received
原 因: sigtest是前臺進(jìn)程,終端關(guān)閉后,根據(jù)上面提到的第1種情況,login shell作為session首進(jìn)程,會收到SIGHUP信號然后退出。根據(jù)第2種情況,sigtest作為前臺進(jìn)程,會收到login shell發(fā)出的SIGHUP信號。
2、命 令:sigtest back > tt.txt &
操 作:關(guān)閉終端
結(jié) 果:tt.txt文件的內(nèi)容為 back : sighup received
原 因: sigtest是提交的job,根據(jù)上面提到的第1種情況,sigtest會收到SIGHUP信號。
3、命 令:寫一個shell,內(nèi)容為[sigtest &],然后執(zhí)行該shell
操 作:關(guān)閉終端
結(jié) 果:ps -ef | grep sigtest 會看到該進(jìn)程還在,tt文件為空
原 因: 執(zhí)行該shell時,sigtest作為job提交,然后該shell退出,致使sigtest變成了孤兒進(jìn)程,不再是當(dāng)前session的job了,因此sigtest即不是session首進(jìn)程也不是job,不會收到SIGHUP。同時孤兒進(jìn)程屬于后臺進(jìn)程,因此login shell退出后不會發(fā)送SIGHUP給sigtest,因?yàn)樗粚⒃撔盘柊l(fā)送給前臺進(jìn)程。第3條說過若進(jìn)程組變成孤兒進(jìn)程組的時候,若有進(jìn)程處于停止?fàn)顟B(tài),也會收到SIGHUP信號,但sigtest沒有處于停止?fàn)顟B(tài),所以不會收到SIGHUP信號。
4、命 令:nohup sigtest > tt
操 作:關(guān)閉終端
結(jié) 果:tt文件為空
原 因: nohup可以防止進(jìn)程收到SIGHUP信號
至此,我們就清楚了何種情況下終端關(guān)閉后進(jìn)程會退出,何種情況下不會退出。
要想終端關(guān)閉后進(jìn)程不退出有以下幾種方法,均為通過shell的方式:
1、編寫shell,內(nèi)容如下
trap "" SIGHUP #該句的作用是屏蔽SIGHUP信號,trap可以屏蔽很多信號
sigtest
2、nohup sigtest 可以直接在命令行執(zhí)行,
若想做完該操作后繼續(xù)別的操作,可以 nohup sigtest &
3、編寫shell,內(nèi)容如下
sigtest &
其實(shí)任何將進(jìn)程變?yōu)楣聝哼M(jìn)程的方式都可以,包括fork后父進(jìn)程馬上退出。
2.SIGCHLD信號 子進(jìn)程死后,會發(fā)送SIGCHLD信號給父進(jìn)程。 一個進(jìn)程在調(diào)用exit命令結(jié)束自己的生命的時候,其實(shí)它并沒有真正的被銷毀,而是留下一個稱為僵尸進(jìn)程(Zombie)的數(shù)據(jù)結(jié)構(gòu)(系統(tǒng)調(diào)用exit,它的作用是使進(jìn)程退出,但也僅僅限于將一個正常的進(jìn)程變成一個僵尸進(jìn)程,并不能將其完全銷毀)。在Linux進(jìn)程的狀態(tài)中,僵尸進(jìn)程 是非常特殊的一種,它已經(jīng)放棄了幾乎所有內(nèi)存空間,沒有任何可執(zhí)行代碼,也不能被調(diào)度,僅僅在進(jìn)程列表中保留一個位置,記載該進(jìn)程的退出狀態(tài)等信息供其他進(jìn)程收集,除此之外,僵尸進(jìn)程不再占有任何內(nèi)存空間。它需要它的父進(jìn)程來為它收尸,如果他的父進(jìn)程沒安裝SIGCHLD信號處理函數(shù)調(diào)用wait或waitpid()等待子進(jìn)程結(jié)束,又沒有顯式忽略該信號,那么它就一直保持僵尸狀態(tài),如果這時父進(jìn)程結(jié)束了,那么init進(jìn)程自動會接手這個子進(jìn)程,為它收尸,它還是能被清除的。但是如果如果父進(jìn)程是一個循環(huán),不會結(jié)束,那么子進(jìn)程就會一直保持僵尸狀態(tài),這就是為什么系統(tǒng)中有時會有很多的僵尸進(jìn)程。 2.SIGTERM信號 kill() 可以發(fā) SIGTERM 過去;kill 命令默認(rèn)也使用 SIGTERM 信號。 |
$ kill -l 列表中,編號為1 ~ 31的信號為傳統(tǒng)UNIX支持的信號,是不可靠信號(非實(shí)時的),編號為32 ~ 63的信號是后來擴(kuò)充的,稱做可靠信號(實(shí)時信號)。不可靠信號和可靠信號的區(qū)別在于前者不支持排隊(duì),可能會造成信號丟失,而后者不會。 下面我們對編號小于SIGRTMIN的信號進(jìn)行討論。 1) SIGHUP 登錄Linux時,系統(tǒng)會分配給登錄用戶一個終端(Session)。在這個終端運(yùn)行的所有程序,包括前臺進(jìn)程組和后臺進(jìn)程組,一般都屬于這個 Session。當(dāng)用戶退出Linux登錄時,前臺進(jìn)程組和后臺有對終端輸出的進(jìn)程將會收到SIGHUP信號。這個信號的默認(rèn)操作為終止進(jìn)程,因此前臺進(jìn) 程組和后臺有終端輸出的進(jìn)程就會中止。不過可以捕獲這個信號,比如wget能捕獲SIGHUP信號,并忽略它,這樣就算退出了Linux登錄,wget也 能繼續(xù)下載。 此外,對于與終端脫離關(guān)系的守護(hù)進(jìn)程,這個信號用于通知它重新讀取配置文件。 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD 如果父進(jìn)程沒有處理這個信號,也沒有等待(wait)子進(jìn)程,子進(jìn)程雖然終止,但是還會在內(nèi)核進(jìn)程表中占有表項(xiàng),這時的子進(jìn)程稱為僵尸進(jìn)程。這種情 況我們應(yīng)該避免(父進(jìn)程或者忽略SIGCHILD信號,或者捕捉它,或者wait它派生的子進(jìn)程,或者父進(jìn)程先終止,這時子進(jìn)程的終止自動由init進(jìn)程來接管)。 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 在以上列出的信號中,程序不可捕獲、阻塞或忽略的信號有:SIGKILL,SIGSTOP 此外,SIGIO在SVR4是退出,在4.3BSD中是忽略;SIGCONT在進(jìn)程掛起時是繼續(xù),否則是忽略,不能被阻塞。 |