Linux內(nèi)核設(shè)計(jì)與實(shí)現(xiàn) 進(jìn)程管理3: 進(jìn)程終止

進(jìn)程終止

? ? ? ? 當(dāng)一個(gè)進(jìn)程顯示地調(diào)用*exit()函數(shù),或者隱式地在main()函數(shù)中返回(C 編譯器自動(dòng)地在main()后調(diào)用exit()函數(shù))時(shí),進(jìn)程即終止了。

????????進(jìn)程也有可能非自愿地終止。當(dāng)進(jìn)程收到某些信號(hào)或產(chǎn)生異常,并且無(wú)法忽略,改變處理方式時(shí)。進(jìn)程依照默認(rèn)的做法終止。

? ? ? ? 不管進(jìn)程以什么方式終止,都要調(diào)用do_exit()函數(shù),這個(gè)函數(shù)定義在<kernel/exit.c>中。


do_exit() 1

? ? ? ? ? ?1. 將進(jìn)程描述符的flags成員設(shè)置為PF_EXITING。

? ? ? ? ? ?2.? 調(diào)用del_timer_sync()益處內(nèi)核定時(shí)器。保證不會(huì)再有定時(shí)器和定時(shí)器處理程序運(yùn)行。

? ? ? ? ? ?3.?profile_task_exit()效果不明。? ???

? ? ? ? ? ?4. 對(duì)ptrace的操作暫時(shí)不知。? ???


do_exit() 2

? ? ? ? ?????5.acct_process()書寫計(jì)數(shù)信息。

? ? ? ? ? ? ?6.__exit_mm()釋放進(jìn)程描述符的mm_struct成員。當(dāng)該地址空間不被其他進(jìn)程分享時(shí),順便釋放此塊內(nèi)存。

? ? ? ? ? ? ?7.exit_sem()如果該進(jìn)程正在排隊(duì)等待IPC信號(hào),那么退出等待隊(duì)列。

? ? ? ? ? ? ?8.exit_notify()向父進(jìn)程發(fā)送信號(hào),并且將子進(jìn)程的父進(jìn)程設(shè)置為同一線程組的其他線程,或者是init進(jìn)程。

? ? ? ? ? ? ?9.schedule()調(diào)度,運(yùn)行到其他進(jìn)程。

? ? ? ? 中止進(jìn)程將轉(zhuǎn)變?yōu)門ASK_ZOMBLE狀態(tài),其唯一對(duì)內(nèi)存空間的利用就是內(nèi)核棧,因?yàn)楸A袅藅hread_info和task_struct兩個(gè)數(shù)據(jù)結(jié)構(gòu),直到其父進(jìn)程調(diào)用了wait4()。

移除進(jìn)程描述符

? ? ? ? wait()函數(shù)族基本做法,調(diào)用<kernel/exit.c>中的release_task()函數(shù)(詳見《Linux內(nèi)核設(shè)計(jì)與實(shí)現(xiàn)》第37頁(yè)):


release_task() 1
release_task() 2

? ? ? ? 1.調(diào)用free_uid()來(lái)減少該進(jìn)程擁有者的進(jìn)程使用計(jì)數(shù),當(dāng)該計(jì)數(shù)為0,則該用戶的cache被銷毀。

? ? ? ? 2.調(diào)用unhash_process()從pidhash上刪除該進(jìn)程(其實(shí)并未顯式地調(diào)用該函數(shù),而是將其語(yǔ)句分散開調(diào)用了),同時(shí)也要從task_list中刪除? ? ? ?該進(jìn)程。

? ? ? ? 3.如果這個(gè)進(jìn)程正在被ptrace追蹤,將追蹤進(jìn)程的父進(jìn)程重設(shè)為其最初的父進(jìn)程并將它從ptrace_list上刪除。

? ? ? ? 4.最后,調(diào)用put_task_struct釋放進(jìn)程內(nèi)核棧和thread_info結(jié)構(gòu)所占的頁(yè),并釋放task_struct所占的slab高速緩存。

? ? ? ? 關(guān)于slab可在學(xué)習(xí)slab機(jī)制

無(wú)父進(jìn)程的困境

????????與《Linux內(nèi)核設(shè)計(jì)與實(shí)現(xiàn)》第二版中表述不同,do_exit()并未調(diào)用notify_parent(),而是調(diào)用了上文提過(guò)的exit_notify(),進(jìn)而調(diào)用forget_original_parent()來(lái)完成改變父進(jìn)程的工作。


exit_notify() 片段

????????上圖中可以看到,exit_notify()函數(shù)甚至還處理了因?yàn)楸具M(jìn)程退出而產(chǎn)生孤兒進(jìn)程組的情況。其實(shí)exit_notify()還囊括了許多情況,不一一列舉。下圖為forget_original_parent()函數(shù):


forget_original_parent()

? ? ? ? 需要注意的是 1.child_reaptr 指向init進(jìn)程。 2.?list_for_each_safe(){} 作用未知,疑似為某種循環(huán)體。 ????

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容