進(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>中。

? ? ? ? ? ?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í)不知。? ???

? ? ? ? ?????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è)):


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

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