孤兒進(jìn)程組和終端會(huì)話 (轉(zhuǎn))
Posted on 2012-12-16 10:42 鑫龍 閱讀(389) 評(píng)論(0) 編輯 收藏 引用 所屬分類: linux編程孤兒進(jìn)程: 即一個(gè)其父進(jìn)程已經(jīng)終止的進(jìn)程。 孤兒進(jìn)程由 init 進(jìn)程“收養(yǎng)”,init 進(jìn)程ID為1,因此被收養(yǎng)的孤兒進(jìn)程的父進(jìn)程便更新為1。
孤兒進(jìn)程組: 一個(gè)進(jìn)程組中的所有進(jìn)程的父進(jìn)程要么是該進(jìn)程組的一個(gè)進(jìn)程,要么不是該進(jìn)程組所在的會(huì)話中的進(jìn)程。 一個(gè)進(jìn)程組不是孤兒進(jìn)程組的條件是,該組中有一個(gè)進(jìn)程其父進(jìn)程在屬于同一個(gè)會(huì)話的另一個(gè)組中。
GNU解釋了為什么會(huì)提出孤兒進(jìn)程組的概念:
When a controlling process terminates, its terminal becomes free and a new session can be established on it. (In fact, another user could log in on the terminal.) This could cause a problem if any processes from the old session are still trying to use that terminal.
To prevent problems, process groups that continue running even after the session leader has terminated are marked as orphaned process groups.
When a process group becomes an orphan, its processes are sent a SIGHUP signal. Ordinarily, this causes the processes to terminate. However, if a program ignores this signal or establishes a handler for it, it can continue running as in the orphan process group even after its controlling process terminates; but it still cannot access the terminal any more.
當(dāng)一個(gè)終端控制進(jìn)程(即會(huì)話首進(jìn)程)終止后,那么這個(gè)終端可以用來建立一個(gè)新的會(huì)話。這可能會(huì)產(chǎn)生一個(gè)問題,原來舊的會(huì)話(一個(gè)或者多個(gè)進(jìn)程組的集合)中的任一進(jìn)程可再次訪問這個(gè)的終端。為了防止這類問題的產(chǎn)生,于是就有了孤兒進(jìn)程組的概念。當(dāng)一個(gè)進(jìn)程組成為孤兒進(jìn)程組時(shí),posix.1要求向孤兒進(jìn)程組中處于停止?fàn)顟B(tài)的進(jìn)程發(fā)送SIGHUP(掛起)信號(hào),系統(tǒng)對(duì)于這種信號(hào)的默認(rèn)處理是終止進(jìn)程,然而如果無(wú)視這個(gè)信號(hào)或者另行處理的話那么這個(gè)掛起進(jìn)程仍可以繼續(xù)執(zhí)行。
以下摘自網(wǎng)絡(luò):
終端的問題涉及幾個(gè)概念,那就是進(jìn)程組,會(huì)話,作業(yè),下面會(huì)分別進(jìn)行介紹。會(huì)話包含了一系列的進(jìn)程,這些進(jìn)程按照不同的執(zhí)行內(nèi)容會(huì)組織成若干進(jìn)程組,一個(gè)會(huì)話內(nèi)的所有進(jìn)程都必須是該會(huì)話首長(zhǎng)進(jìn)程的后代,這樣就保證了這些進(jìn)程都是由該會(huì)話首長(zhǎng)進(jìn)程直接或者間接開啟的,只有這樣的才能保證這些進(jìn)程確實(shí)是在會(huì)話首長(zhǎng)進(jìn)程耳目視線之內(nèi)的,同時(shí),孤兒進(jìn)程組不再受到會(huì)話首長(zhǎng)進(jìn)程的控制。
作業(yè):
只有一個(gè)終端,但是有很多事情要同時(shí)做,或者起碼分時(shí)做,不能先做完一件事再做另一件,怎么辦?畢竟啟動(dòng)一個(gè)進(jìn)程后該進(jìn)程就會(huì)獨(dú)占終端啊,畢竟shell會(huì)將它設(shè)置為前臺(tái)進(jìn)程組進(jìn)程啊。這就是作業(yè)的功能,只需要在一個(gè)命令后加一個(gè)&符號(hào)就可以了,比如我要執(zhí)行x,那么就敲入:
x &
shell的結(jié)果是:
[1] 1234
此處1234是進(jìn)程的pid,而1則是作業(yè)的id,這樣這個(gè)x就不占用終端了,shell可以啟動(dòng)其它的進(jìn)程或者作業(yè)了,比如又啟動(dòng)了作業(yè)2:
[2] 4321
此時(shí)想起作業(yè)1需要使用一下終端來輸入一些信息了,那么就使用:fg %1將作業(yè)1置于前臺(tái)(作業(yè)1中目前只有一個(gè)進(jìn)程),置于前臺(tái)的作業(yè)如何重新放到后臺(tái)呢?只需要用SIGSTOP信號(hào)停止前臺(tái)使用終端的進(jìn)程即可,然后該進(jìn)程就放開終端的占用了
進(jìn)程組:一個(gè)作業(yè)就是一個(gè)進(jìn)程組,單獨(dú)的進(jìn)程可以獨(dú)占一個(gè)進(jìn)程組也可以加入同一會(huì)話的別的進(jìn)程組,必須要滿足的條件是,同一進(jìn)程組的所有進(jìn)程都要是一個(gè)會(huì)話的后代。所謂的進(jìn)程組是為了組織作業(yè)或者組織同一類任務(wù)的。
控制終端:
一個(gè)會(huì)話的建立者有權(quán)力申請(qǐng)一個(gè)控制終端,在該控制終端中可以接受標(biāo)準(zhǔn)輸入,可以發(fā)送shell理解的控制快捷鍵,可以創(chuàng)建作業(yè)并且使用會(huì)話頭進(jìn)程提供的作業(yè)控制功能。控制終端只能由會(huì)話頭進(jìn)程創(chuàng)建,并且控制終端是獨(dú)占的,只要有一個(gè)進(jìn)程將一個(gè)終端當(dāng)成了控制終端,別的進(jìn)程不管它是誰(shuí)都不能這么做了,tty_open中的最后有下面幾行代碼
if (!noctty &&
current->signal->leader &&
!current->signal->tty &&
tty->session == 0) {
task_lock(current);
current->signal->tty = tty;
task_unlock(current);
current->signal->tty_old_pgrp = 0;
tty->session = current->signal->session; //設(shè)置session
tty->pgrp = process_group(current);
}
可見別的進(jìn)程是無(wú)權(quán)申請(qǐng)控制終端的。
這個(gè)控制終端平時(shí)給誰(shuí)用呢?最不容被懷疑的會(huì)話首長(zhǎng)申請(qǐng)了終端,因?yàn)槿绻B他都值得懷疑的話,后面的屬于他的孩子進(jìn)程們都值得懷疑了,首長(zhǎng)申請(qǐng)的終端就是給這些孩子們用的,首長(zhǎng)將這些孩子們分成了若干的進(jìn)程組,指定一個(gè)組為前臺(tái)進(jìn)程組,只有這個(gè)前臺(tái)進(jìn)程組的進(jìn)程才能使用控制終端。bash一般會(huì)作為會(huì)話首長(zhǎng)存在,bash將為一個(gè)執(zhí)行的命令都創(chuàng)建一個(gè)進(jìn)程組,它在接受一個(gè)命令準(zhǔn)備執(zhí)行的時(shí)候會(huì)將該進(jìn)程設(shè)置為前臺(tái)進(jìn)程組,它在接受了命令行后加&的命令時(shí),會(huì)創(chuàng)建一個(gè)作業(yè),并且將它設(shè)定為后臺(tái)進(jìn)程組,那么此時(shí)前臺(tái)是誰(shuí)呢,是bash自己哦。后臺(tái)進(jìn)程不能使用終端,如果使用&執(zhí)行了內(nèi)部帶有諸如getchar之類函數(shù)的進(jìn)程,那么其將會(huì)收到SIGTTIN信號(hào),不過可以使用fg命令將這類進(jìn)程提到前臺(tái)。
控制進(jìn)程:
很顯然,首先控制進(jìn)程是一個(gè)會(huì)話的首長(zhǎng)進(jìn)程,另外即使是會(huì)話首長(zhǎng)也只能通過終端來控制別的進(jìn)程,所謂的控制就是發(fā)送信號(hào)而不是操作內(nèi)存之類的,這也是進(jìn)程間通信的一種方式。因此所謂的控制進(jìn)程就是申請(qǐng)到控制終端的進(jìn)程。
孤兒進(jìn)程組:
有孤兒進(jìn)程,對(duì)應(yīng)的也有孤兒進(jìn)程組的概念。為何引入這個(gè)概念以及這個(gè)概念的引入需要OS的實(shí)現(xiàn)者作些什么呢?先看兩個(gè)前提,首先,posix用一個(gè)session的概念來描述一次用戶的登錄以及該用戶在此次登錄后的操作,然后用作業(yè)的概念描述不同操作的內(nèi)容,最后才用進(jìn)程的概念描述不同操作中某一個(gè)具體的工作;其次,unix最初將所有的進(jìn)程組織成了樹的形式,這樣就便于追蹤每個(gè)進(jìn)程也便于管理(想想看,人類政治社會(huì)也是一個(gè)類似樹形結(jié)構(gòu):君主專制,兩院制等)。有了上述兩個(gè)前提事情就很明白了,一切都是為了便于管理,一切都是為了登錄用戶的安全,即此次登錄用戶的作業(yè)是不能被下個(gè)登錄用戶所控制的,即使它們的用戶名一致也是不行的,因此所謂的孤兒進(jìn)程組簡(jiǎn)單點(diǎn)說就是脫離了創(chuàng)造它的session控制的,離開其session眼線的進(jìn)程組,unix中怎樣控制進(jìn)程,怎樣證明是否在自己的眼線內(nèi),那就是樹形結(jié)構(gòu)了,只要處于以自己為根的子樹的進(jìn)程就是自己眼線內(nèi)的進(jìn)程,這個(gè)進(jìn)程就是受到保護(hù)的,有權(quán)操作的,而在別的樹枝上的進(jìn)程原則上是觸動(dòng)不得的(又想說說windows的遠(yuǎn)程線程創(chuàng)建了,可是說的話還要接著說其復(fù)雜的令牌機(jī)制,否則windows粉絲不服氣,所以不說了罷),unix中建立進(jìn)程使用fork,自然地這么一“叉子”就形成了自己的一個(gè)樹枝,當(dāng)然在自己眼線了,一般對(duì)于登錄用戶而言一個(gè)會(huì)話起始于一次login之后的shell,只要該用戶不logout,在該終端的shell上執(zhí)行的所有的非守護(hù)進(jìn)程都是該shell的后代進(jìn)程,因此它們組成一個(gè)會(huì)話,全部在shell的眼線中,一個(gè)會(huì)話終止于會(huì)話首長(zhǎng)的death。現(xiàn)在考慮一下終端上的shell退出后的情景,按照規(guī)定,該終端上所有的進(jìn)程都過繼給了別的進(jìn)程,大多數(shù)情況是init進(jìn)程,然后緊接著另外一個(gè)用戶登錄了這個(gè)終端或者知道前一個(gè)登錄用戶密鑰的另一個(gè)有不好念頭的人登錄了該終端,當(dāng)然為其啟動(dòng)的shell創(chuàng)建了一個(gè)新的session,由于之前登錄的用戶已退出,現(xiàn)在登錄的用戶由于之前用戶的進(jìn)程組都成了孤兒進(jìn)程組,所以它再有惡意也不能控制它們了,那些孤兒進(jìn)程組中的成員要么繼續(xù)安全的運(yùn)行,要么被shell退出時(shí)發(fā)出的SIGHUP信號(hào)殺死。
POSIX的規(guī)定是鐵的紀(jì)律,而unix或者linux的不管是內(nèi)核還是shell的實(shí)現(xiàn)則是一種遵守紀(jì)律的方式,鐵的紀(jì)律要求作業(yè)控制要以session為基本,就是說不能操作別的session內(nèi)的進(jìn)程組,所以類似fg和bg等命令就不能操作孤兒進(jìn)程,因此如果由于后臺(tái)進(jìn)程組由于讀寫終端被SIGSTOP信號(hào)停了,而后它又成了孤兒進(jìn)程組的成員,那怎么辦?別的session的作業(yè)控制命令又不能操作它,即使ps -xj找到了它然后手工發(fā)送了SIGCONT,那么它還是沒法使用終端,這是POSIX的另一個(gè)紀(jì)律要求的,只有唯一和終端關(guān)聯(lián)的session中的前臺(tái)進(jìn)程組的進(jìn)程可以使用終端,因此只要有一個(gè)shell退出了,最好的辦法就是將其session內(nèi)的所有的進(jìn)程都干掉,因此SIGHUP的原意就是如此,但是完全可以忽略這個(gè)信號(hào)或者自己定義對(duì)該信號(hào)的反應(yīng)。POSIX的基本限制就是session的ID是不能設(shè)置的,因?yàn)樗鞘鼙Wo(hù)的基本單位,但是進(jìn)程組的ID是可以設(shè)置的,畢竟它只是區(qū)分了不能的作業(yè),最后進(jìn)程的PID也是不能設(shè)置的,因?yàn)樗沁M(jìn)程的內(nèi)秉屬性,形成樹形進(jìn)程結(jié)構(gòu)的關(guān)鍵屬性。
POSIX對(duì)孤兒進(jìn)程組的定義:組中沒有一個(gè)進(jìn)程的父進(jìn)程和自己屬于同一個(gè)會(huì)話但是不同進(jìn)程組的。
轉(zhuǎn)自 http://xingyunbaijunwei.blog.163.com/blog/static/765380672011112633634628/