2.進(jìn)程管理

進(jìn)程管理

進(jìn)程是操作系統(tǒng)的基本概念鳄逾,本節(jié)主要總結(jié)Linux內(nèi)核如何管理進(jìn)程:進(jìn)程在內(nèi)核中如何創(chuàng)建,消亡灵莲。

1.進(jìn)程

進(jìn)程是處于執(zhí)行期的程序雕凹,但不僅包含可執(zhí)行的程序代碼,還包括其他資源:打開(kāi)的文件政冻、掛起的信號(hào)枚抵、內(nèi)核內(nèi)部數(shù)據(jù)處理器狀態(tài)明场、一個(gè)或多個(gè)具有內(nèi)存映射的內(nèi)存地址空間和執(zhí)行線程以及存放全局變量的數(shù)據(jù)段等汽摹。

線程

執(zhí)行線程,簡(jiǎn)稱線程榕堰,是進(jìn)程中活動(dòng)的對(duì)象竖慧。擁有獨(dú)立的程序計(jì)數(shù)器進(jìn)程棧進(jìn)程寄存器逆屡。內(nèi)核調(diào)度的對(duì)象是線程而不是進(jìn)程圾旨,在Linux中線程是一種特殊的進(jìn)程。

2.進(jìn)程描述符

內(nèi)核把進(jìn)程的列表存放在叫做任務(wù)隊(duì)列(task list)的雙向循環(huán)列表中(列表插入刪除復(fù)雜度低)魏蔗。列表的每一項(xiàng)類(lèi)型都是task_struct稱為進(jìn)程描述符(process description)砍的,進(jìn)程描述符能夠完整的描述一個(gè)正在執(zhí)行的程序。

分配進(jìn)程描述符

Linux通過(guò)slab分配task_struct結(jié)構(gòu)莺治,在棧底(向下增長(zhǎng)的棧)創(chuàng)建一個(gè)新的結(jié)構(gòu)struct thread_info用于存放task_struct的偏移地址廓鞠,這樣方便定位task_struct的實(shí)際指針。

進(jìn)程描述符的存放

內(nèi)核中大部分處理進(jìn)程的代碼都是直接訪問(wèn)task_struct指針谣旁,通過(guò)current宏查找當(dāng)前正在運(yùn)行進(jìn)程的進(jìn)程描述符床佳。但是像x86寄存器較少,因此只能通過(guò)內(nèi)核棧的尾端創(chuàng)建thread_info來(lái)計(jì)算偏移地址查找task_struct榄审。

進(jìn)程狀態(tài)

進(jìn)程描述符中的state域描述了進(jìn)程的當(dāng)前狀態(tài)砌们。進(jìn)程狀態(tài)處于下列五種狀態(tài)之一:

  • TASK_RUNNING(運(yùn)行)——進(jìn)程可執(zhí)行,處于執(zhí)行中或者運(yùn)行隊(duì)列中等待
  • TASK_INTERRUPTIBLE(可中斷)——進(jìn)程正在睡眠(被阻塞),等待某些條件達(dá)成浪感。也可以通過(guò)接收信號(hào)提前被喚醒并隨時(shí)準(zhǔn)備投入運(yùn)行
  • TASK_UNITTERUPTIBLE(不可中斷)——對(duì)信號(hào)不做相應(yīng)昔头,其余和可中斷狀態(tài)相同,通常用于重要且不能中斷的進(jìn)程
  • __TASK_TRACED——被其他進(jìn)程跟蹤的進(jìn)程影兽,例如通過(guò)ptrace對(duì)調(diào)試程序進(jìn)行跟蹤
  • __TASK_STOPPED(停止)——進(jìn)程停止執(zhí)行揭斧,進(jìn)程沒(méi)有投入運(yùn)行也不能投入運(yùn)行
進(jìn)程狀態(tài)轉(zhuǎn)移圖

設(shè)置當(dāng)前進(jìn)程狀態(tài)

內(nèi)核調(diào)整某個(gè)進(jìn)程的狀態(tài),可以通過(guò)如下代碼:

set_task_state(task,state);

或者

task->state = state;

設(shè)置當(dāng)前狀態(tài)峻堰,可以通過(guò)set_current_state(state)set_task_state(current,state)

進(jìn)程上下文

一般程序在用戶空間執(zhí)行讹开,一旦程序執(zhí)行了系統(tǒng)調(diào)用或者觸發(fā)某個(gè)異常,它就陷入內(nèi)核空間(對(duì)應(yīng)第一節(jié)內(nèi)容)捐名。除非在內(nèi)核空間運(yùn)行期間有更高優(yōu)先級(jí)的進(jìn)程需要執(zhí)行并由調(diào)度器做出了相應(yīng)的調(diào)整萧吠,否則在內(nèi)核退出的時(shí)候,程序恢復(fù)在用戶空間繼續(xù)執(zhí)行桐筏。

系統(tǒng)調(diào)用和異常處理程序是對(duì)內(nèi)核明確定義的接口。進(jìn)程只有通過(guò)這些接口才能陷入內(nèi)核執(zhí)行拇砰,對(duì)內(nèi)核的所有訪問(wèn)必須通過(guò)這些接口梅忌。

進(jìn)程家族樹(shù)

Unix系統(tǒng)的進(jìn)程之間存在明顯的繼承關(guān)系,Linux也是如此除破。內(nèi)核在系統(tǒng)啟動(dòng)最后階段執(zhí)行了init進(jìn)程牧氮,該進(jìn)程讀取系統(tǒng)初始化腳本并執(zhí)行其他相關(guān)程序,最終完成系統(tǒng)啟動(dòng)的整個(gè)過(guò)程瑰枫,PID為1踱葛,所以所有進(jìn)程都是init的后代。因此每個(gè)進(jìn)程標(biāo)識(shí)符都有一個(gè)指向父親的task->parent指針光坝,和子進(jìn)程鏈表&task->children尸诽。

由于任務(wù)隊(duì)列是一個(gè)雙向循環(huán)鏈表,我們可以通過(guò)下面兩種方式分別獲取前一個(gè)和后一個(gè)進(jìn)程:

list_entry(task->tasks.next, struct task_struct, tasks)

list_entry(task->tasks.next, struct task_struct, tasks)

3.進(jìn)程創(chuàng)建

許多操作系統(tǒng)進(jìn)程創(chuàng)建過(guò)程為盯另,首先在新的地址空間創(chuàng)建進(jìn)程性含,讀入可執(zhí)行文件,最后執(zhí)行鸳惯。而Unix將上述兩個(gè)步驟分解到兩個(gè)單獨(dú)的函數(shù)去執(zhí)行:fork()exec()商蕴。

首先,fork()通過(guò)拷貝當(dāng)前進(jìn)程創(chuàng)建子進(jìn)程芝发,子進(jìn)程與父進(jìn)程區(qū)別僅僅在于PID和PPID和某些資源和統(tǒng)計(jì)量绪商。

然后,exec()負(fù)責(zé)讀取可執(zhí)行文件并將其載入地址空間運(yùn)行辅鲸。

寫(xiě)時(shí)拷貝

Linux的fork()函數(shù)進(jìn)行了一個(gè)優(yōu)化格郁,采用寫(xiě)時(shí)拷貝實(shí)現(xiàn)。在創(chuàng)建進(jìn)程階段,內(nèi)核并不復(fù)制整個(gè)地址空間理张,而是讓父進(jìn)程和子進(jìn)程共享同一個(gè)拷貝赫蛇。

進(jìn)程只有在需要寫(xiě)入時(shí),才復(fù)制數(shù)據(jù)雾叭,這樣將頁(yè)拷貝推遲到寫(xiě)入階段悟耘,可以使Linux進(jìn)程快速啟動(dòng),并且往往進(jìn)程在fork()之后會(huì)馬上exec()织狐,不會(huì)有寫(xiě)入過(guò)程(這個(gè)優(yōu)化過(guò)程還是相當(dāng)機(jī)智暂幼,Linux快啟動(dòng)的靈魂!)

fork()

由前面介紹我們了解了進(jìn)程需要fork()拷貝父進(jìn)程的信息移迫,Linux通過(guò)clone()系統(tǒng)調(diào)用實(shí)現(xiàn)fork()旺嬉,其功能主要通過(guò)cope_process()函數(shù)實(shí)現(xiàn):

  1. 調(diào)用dup_task_struct()為新進(jìn)程創(chuàng)建一個(gè)內(nèi)核棧,thread_info結(jié)構(gòu)和task_struct厨埋,這些值與父進(jìn)程完全相同
  2. 檢查并確保創(chuàng)建子進(jìn)程后邪媳,當(dāng)前用戶的進(jìn)程數(shù)沒(méi)有超過(guò)限制
  3. 區(qū)分子進(jìn)程和父進(jìn)程,講進(jìn)程描述符中許多成員清零或初始化(主要是統(tǒng)計(jì)信息)荡陷,多數(shù)數(shù)據(jù)仍未修改
  4. 子進(jìn)程的狀態(tài)設(shè)置為T(mén)ASK_UNINTERRUPTIBLE雨效,保證其不會(huì)被運(yùn)行
  5. 調(diào)用copy_flags()更新進(jìn)程描述符的flag成員,表明是否擁有超級(jí)用戶權(quán)限的標(biāo)志PF_SUPERPRIV標(biāo)志清零废赞,表明進(jìn)程沒(méi)有調(diào)用exec()函數(shù)的PF_FORKNOEXEC標(biāo)志被設(shè)置徽龟。
  6. 調(diào)用alloc_pid()為新進(jìn)程分配一個(gè)有效PID
  7. 根據(jù)傳遞給clone()的參數(shù)標(biāo)志,cope_process()拷貝或共享打開(kāi)的文件唉地、文件系統(tǒng)信息据悔、信號(hào)處理函數(shù)、進(jìn)程地址空間和命名空間等耘沼。通常對(duì)于制定進(jìn)程的線程极颓,這些資源都是共享;否則耕拷,這些資源對(duì)每個(gè)進(jìn)程都是不同的讼昆,往往需要拷貝到這里。
  8. copy_process()掃尾骚烧,并返回一個(gè)指向子進(jìn)程的指針

一般內(nèi)核會(huì)有意讓子進(jìn)程先執(zhí)行浸赫,減小寫(xiě)時(shí)拷貝可能的開(kāi)銷(xiāo)。

vfork()

對(duì)于vfork()赃绊,其不拷貝父進(jìn)程的頁(yè)表項(xiàng)既峡,子進(jìn)程會(huì)作為父進(jìn)程的一個(gè)線程執(zhí)行,父進(jìn)程被阻塞碧查,直到子進(jìn)程退出或者執(zhí)行exec()运敢。子進(jìn)程不能向地址空間寫(xiě)入校仑。

4.線程在Linux中實(shí)現(xiàn)

Linux中線程只是共享父進(jìn)程資源的輕量進(jìn)程,其創(chuàng)建方式和普通進(jìn)程類(lèi)似传惠,只是在調(diào)用clone()時(shí)迄沫,需要傳遞一些參數(shù)標(biāo)志位,表明需要共享的資源:

clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);

而普通的進(jìn)程為:

clone(SIGHLD, 0);

其中CLONE_VM——父子進(jìn)程共享地址空間卦方;CLONE_FS——共享文件系統(tǒng)信息羊瘩;CLONE_FILES——共享打開(kāi)的文件;CLONE_SIGHAND——共享信號(hào)處理函數(shù)和被阻斷的信號(hào)盼砍;

5.進(jìn)程終結(jié)

進(jìn)程終結(jié)一般是自身引起的尘吗,它發(fā)生在進(jìn)程調(diào)用exit()系統(tǒng)調(diào)用時(shí)。當(dāng)進(jìn)程接收到它不能處理且不能忽略的信號(hào)或者異常時(shí)浇坐,也可能被動(dòng)終結(jié)睬捶。不管什么原因終結(jié),進(jìn)程終結(jié)的大部分工作由do_exit()完成:

  1. task_struct的標(biāo)志成員設(shè)置為PF_EXITING
  2. 調(diào)用del_timer_sync()刪除任意內(nèi)核定時(shí)器近刘。根據(jù)返回結(jié)果擒贸,確保沒(méi)有定時(shí)器在排隊(duì),也沒(méi)有定時(shí)器處理程序在運(yùn)行
  3. 若BSD的進(jìn)程記賬功能開(kāi)啟的觉渴,調(diào)用acct_update_integrals()來(lái)輸出記賬信息
  4. 調(diào)用exit_mm()函數(shù)釋放進(jìn)程占用的mm_struct酗宋,若沒(méi)有其他進(jìn)程使用,就徹底釋放
  5. 調(diào)用sem_exit()疆拘。若進(jìn)程排隊(duì)等候IPC信號(hào),則它離開(kāi)隊(duì)列
  6. 調(diào)用exit_files()exit_fs()分別遞減文件描述符寂曹、文件系統(tǒng)數(shù)據(jù)的引用次數(shù)哎迄,若為0,可以釋放
  7. 接著把存放在task_struct的exit_code成員中的任務(wù)退出代碼設(shè)置為由exit()提供的退出代碼隆圆,或者去完成其他由內(nèi)核機(jī)制規(guī)定的退出動(dòng)作漱挚。退出代碼存放在這里供父進(jìn)程隨時(shí)檢索
  8. 調(diào)用exit_notify()向父進(jìn)程發(fā)生信號(hào),給子進(jìn)程重新找養(yǎng)父渺氧,養(yǎng)父為線程組中的其他線程或者init進(jìn)程旨涝,并設(shè)置task_structexit_stateEXIT_ZOMBIE
  9. 調(diào)用schedule()切換到新進(jìn)程

至此進(jìn)程相關(guān)的所有資源都被釋放掉了,并處于EXIT_ZOMBIE狀態(tài)侣背,僅剩內(nèi)核棧白华、thread_info結(jié)構(gòu)和task_struct結(jié)構(gòu)用于給父進(jìn)程提供信息。父進(jìn)程檢索信息后贩耐,或者通知內(nèi)核那是無(wú)關(guān)信息后弧腥,將該內(nèi)存釋放,歸還系統(tǒng)使用潮太。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末管搪,一起剝皮案震驚了整個(gè)濱河市虾攻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌更鲁,老刑警劉巖霎箍,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異澡为,居然都是意外死亡漂坏,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)缀壤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)樊拓,“玉大人,你說(shuō)我怎么就攤上這事塘慕〗钕模” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵图呢,是天一觀的道長(zhǎng)条篷。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蛤织,這世上最難降的妖魔是什么赴叹? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮指蚜,結(jié)果婚禮上乞巧,老公的妹妹穿的比我還像新娘。我一直安慰自己摊鸡,他們只是感情好绽媒,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著免猾,像睡著了一般是辕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上猎提,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天获三,我揣著相機(jī)與錄音,去河邊找鬼锨苏。 笑死疙教,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的伞租。 我是一名探鬼主播松逊,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼肯夏!你這毒婦竟也來(lái)了经宏?” 一聲冷哼從身側(cè)響起犀暑,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎烁兰,沒(méi)想到半個(gè)月后耐亏,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沪斟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年广辰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片主之。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡择吊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出槽奕,到底是詐尸還是另有隱情几睛,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布粤攒,位于F島的核電站所森,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏夯接。R本人自食惡果不足惜焕济,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望盔几。 院中可真熱鬧晴弃,春花似錦、人聲如沸逊拍。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)顺献。三九已至,卻和暖如春枯怖,著一層夾襖步出監(jiān)牢的瞬間注整,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工度硝, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肿轨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓蕊程,卻偏偏與公主長(zhǎng)得像椒袍,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子藻茂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 又來(lái)到了一個(gè)老生常談的問(wèn)題驹暑,應(yīng)用層軟件開(kāi)發(fā)的程序員要不要了解和深入學(xué)習(xí)操作系統(tǒng)呢玫恳? 今天就這個(gè)問(wèn)題開(kāi)始,來(lái)談?wù)劜?..
    tangsl閱讀 4,088評(píng)論 0 23
  • Linux 進(jìn)程管理與程序開(kāi)發(fā) 進(jìn)程是Linux事務(wù)管理的基本單元优俘,所有的進(jìn)程均擁有自己獨(dú)立的處理環(huán)境和系統(tǒng)資源京办,...
    JamesPeng閱讀 2,450評(píng)論 1 14
  • 本文轉(zhuǎn)載自實(shí)驗(yàn)樓:多進(jìn)程(一) 概述 進(jìn)程的概念這里就不再過(guò)多的贅述了,市面上幾乎關(guān)于計(jì)算機(jī)操作系統(tǒng)的書(shū)都有詳細(xì)的...
    mnikn閱讀 487評(píng)論 0 0
  • 大清早,一路聽(tīng)著自己錄的音叶雹,開(kāi)開(kāi)心心的去單位上班财饥。 心想,難得心情這么愉悅折晦,想必今天一定是美好的一天钥星。 走在上班的...
    4e57b8f24a48閱讀 440評(píng)論 1 2
  • 摘自徐靜蕾的朗讀者 世界給我的第一個(gè)記憶是,我躺在奶奶的懷里筋遭,拼命地哭打颤,打著挺兒,也不知道是為什么漓滔,哭得好傷心编饺。奶...
    大老童閱讀 292評(píng)論 0 0