孤儿进程和僵尸进程
前幾天接到某互聯(lián)網(wǎng)公司的電話面試,面試官問我兩次fork()的作用,我一頭霧水,說不知道。知識(shí)面還是太窄了。下面就總結(jié)下兩次fork()的作用。
?
首先,要了解什么叫僵尸進(jìn)程,什么叫孤兒進(jìn)程,以及服務(wù)器進(jìn)程運(yùn)行所需要的一些條件。兩次fork()就是為了解決這些相關(guān)的問題而出現(xiàn)的一種編程方法。
?孤兒進(jìn)程
??????? 孤兒進(jìn)程是指父進(jìn)程在子進(jìn)程結(jié)束之前死亡(return 或exit)。如下圖1所示:
圖1? 孤兒進(jìn)程
但是孤兒進(jìn)程并不會(huì)像上面畫的那樣持續(xù)很長(zhǎng)時(shí)間,當(dāng)系統(tǒng)發(fā)現(xiàn)孤兒進(jìn)程時(shí),init進(jìn)程就收養(yǎng)孤兒進(jìn)程,成為它的父親,child進(jìn)程exit后的資源回收就都由init進(jìn)程來完成。
?
僵尸進(jìn)程
???????? 僵尸進(jìn)程是指子進(jìn)程在父進(jìn)程之前結(jié)束了,但是父進(jìn)程沒有用wait或waitpid回收子進(jìn)程。如下圖所示:
?????
圖2?? 僵尸進(jìn)程
???????? 父進(jìn)程沒有用wait回收子進(jìn)程并不說明它不會(huì)回收子進(jìn)程。子進(jìn)程在結(jié)束的時(shí)候會(huì)給其父進(jìn)程發(fā)送一個(gè)SIGCHILD信號(hào),父進(jìn)程默認(rèn)是忽略SIGCHILD信號(hào)的,如果父進(jìn)程通過signal()函數(shù)設(shè)置了SIGCHILD的信號(hào)處理函數(shù),則在信號(hào)處理函數(shù)中可以回收子進(jìn)程的資源。
????? 事實(shí)上,即便是父進(jìn)程沒有設(shè)置SIGCHILD的信號(hào)處理函數(shù),也沒有關(guān)系,因?yàn)樵诟高M(jìn)程結(jié)束之前,子進(jìn)程可以一直保持僵尸狀態(tài),當(dāng)父進(jìn)程結(jié)束后,init進(jìn)程就會(huì)負(fù)責(zé)回收僵尸子進(jìn)程。
????? 但是,如果父進(jìn)程是一個(gè)服務(wù)器進(jìn)程,一直循環(huán)著不退出,那子進(jìn)程就會(huì)一直保持著僵尸狀態(tài)。雖然僵尸進(jìn)程不會(huì)占用任何內(nèi)存資源,但是過多的僵尸進(jìn)程總還是會(huì)影響系統(tǒng)性能的。黔驢技窮的情況下,該怎么辦呢?
???????? 這個(gè)時(shí)候就需要一個(gè)英雄來拯救整個(gè)世界,它就是兩次fork()技法。
兩次fork()技法
???????? 兩次fork()的流程如下所示:
圖3??? 兩次fork的控制流
???????如上圖3所示,為了避免子進(jìn)程child成為僵尸進(jìn)程,我們可以人為地創(chuàng)建一個(gè)子進(jìn)程child1,再讓child1成為工作子進(jìn)程child2的父進(jìn)程,child2出生后child1退出,這個(gè)時(shí)候child2相當(dāng)于是child1產(chǎn)生的孤兒進(jìn)程,這個(gè)孤兒進(jìn)程由系統(tǒng)進(jìn)程init回收。這樣,當(dāng)child2退出的時(shí)候,init就會(huì)回收child2的資源,child2就不會(huì)成為孤魂野鬼禍國(guó)殃民了。
?
?? <unix環(huán)境高級(jí)編程>這本書里提供了兩次fork的一個(gè)例子,代碼如下:
[cpp]?view plaincopy?????????一言以蔽之,兩次fork()是人為地創(chuàng)建一個(gè)工作子進(jìn)程的父進(jìn)程,然后讓這個(gè)人為父進(jìn)程退出,之后工作子進(jìn)程就由init回收,避免了工作子進(jìn)程成為僵尸進(jìn)程。
轉(zhuǎn)載于:https://www.cnblogs.com/cobbliu/archive/2012/03/10/2388565.html
總結(jié)
- 上一篇: Plenty Of Tricks to
- 下一篇: 成长轨迹59 【ACM算法之路 百炼po