最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Linux內(nèi)核架構(gòu)分析--進(jìn)程管理及調(diào)度學(xué)習(xí)筆記(詳細(xì)記錄)

2022-03-29 20:12 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿
  • 如果系統(tǒng)只有一個(gè)處理器,那么給定時(shí)刻只有一個(gè)程序可以運(yùn)行。在多處理器系統(tǒng)中,真正并行運(yùn)行的進(jìn)程數(shù)目取決于物理CPU的數(shù)目。內(nèi)核和處理器建立了多任務(wù)的錯(cuò)覺,是通過(guò)以很短的間隔在系統(tǒng)運(yùn)行的應(yīng)用程序之間不停切換做到的。由此,以下兩個(gè)問題必須由內(nèi)核解決:除非明確要求,否則應(yīng)用程序不能彼此干擾;CPU時(shí)間必須在各種應(yīng)用程序之間盡可能公平共享(一些程序可能比其他程序更重要)。本篇博文主要涉及內(nèi)核共享CPU時(shí)間的方法以及如何在進(jìn)程之間切換(內(nèi)核為各進(jìn)程分配時(shí)間,保證切換之后從上次撤銷其資源時(shí)執(zhí)行環(huán)境完全相同)。

一、進(jìn)程優(yōu)先級(jí)

  • 并非所有進(jìn)程的重要程度都相同,對(duì)于進(jìn)程,首先比較粗糙的劃分,進(jìn)程可以分為實(shí)時(shí)進(jìn)程和非實(shí)時(shí)進(jìn)程。

  1. 硬實(shí)時(shí)進(jìn)程:有嚴(yán)格的時(shí)間限制,某些任務(wù)必須在指定時(shí)限內(nèi)完成。比如汽車的安全氣囊,一旦發(fā)生碰撞,必須保證在一定時(shí)間內(nèi)觸發(fā),超過(guò)時(shí)限則產(chǎn)生災(zāi)難性的后果。主流的Linux內(nèi)核不支持實(shí)時(shí)處理,但有一些修改版本如RTLinux、Xenomai、RATI提供了這些特性,這些方案中,將Linux內(nèi)核作為獨(dú)立的“進(jìn)程”運(yùn)行處理次要軟件,實(shí)時(shí)工作在Linux內(nèi)核外部完成。

  2. 軟實(shí)時(shí)進(jìn)程:軟實(shí)時(shí)進(jìn)程是硬實(shí)時(shí)進(jìn)程的一種弱化形式,優(yōu)先于其他普通進(jìn)程,稍微晚一點(diǎn)不會(huì)造成巨大影響。比如對(duì)CD的寫入操作。

  3. 普通進(jìn)程:沒有特定時(shí)間約束的進(jìn)程,可以根據(jù)重要性對(duì)其進(jìn)行分配優(yōu)先級(jí)。


  • 圖1是CPU分配時(shí)間的一個(gè)簡(jiǎn)圖。進(jìn)程運(yùn)行按時(shí)間片調(diào)度,分配進(jìn)程的時(shí)間片額與其相對(duì)重要性相當(dāng)。系統(tǒng)中時(shí)間的流動(dòng)對(duì)應(yīng)于圓盤的轉(zhuǎn)動(dòng),重要的進(jìn)程會(huì)比次要的進(jìn)程得到更多CPU時(shí)間,進(jìn)程被切換時(shí),所有的CPU寄存器內(nèi)容和頁(yè)表都會(huì)被保存,下次該進(jìn)程恢復(fù)執(zhí)行時(shí),其執(zhí)行環(huán)境可以完全恢復(fù)。這種簡(jiǎn)化模型忽略了一些進(jìn)程狀態(tài)相關(guān)的信息,不能使CPU時(shí)間利益回報(bào)盡可能最大化。但是為調(diào)度器的質(zhì)量確立一種定量標(biāo)準(zhǔn)非常困難。自Linux內(nèi)核誕生以來(lái),調(diào)度器的代碼已經(jīng)重寫了好幾次。按時(shí)間先后順序,主要有O(n)調(diào)度器,O(1)調(diào)度器和CFS(completely fair scheduler)調(diào)度器。

【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!?。∏?00名進(jìn)群領(lǐng)取,額外贈(zèng)送一份價(jià)值699的內(nèi)核資料包(含視頻教程、電子書、實(shí)戰(zhàn)項(xiàng)目及代碼)?




二、進(jìn)程生命周期

  • 進(jìn)程并不總是可以立即運(yùn)行,有時(shí)候它需要等待來(lái)自外部信號(hào)源、不受其控制的事件(如文本編輯等待輸入)。在調(diào)度器進(jìn)行進(jìn)程切換時(shí),必須知道每個(gè)進(jìn)程的狀態(tài),因?yàn)閷PU事件分配給無(wú)事可做的進(jìn)程沒有意義,進(jìn)程在各個(gè)狀態(tài)之間的轉(zhuǎn)換也同樣重要。


  • 進(jìn)程可能存在的狀態(tài)有:運(yùn)行、等待和睡眠。圖2描述了進(jìn)程的幾種狀態(tài)及其轉(zhuǎn)換。除了圖中所示的幾種狀態(tài)以外,還有一種狀態(tài)被稱為僵尸態(tài)。

  1. 運(yùn)行:該進(jìn)程正在運(yùn)行。

  2. 等待(就緒):進(jìn)程能夠運(yùn)行,但沒有得到許可,因?yàn)镃PU分配給了另一個(gè)進(jìn)程。調(diào)度器可能在下一次任務(wù)切換時(shí)選擇該進(jìn)程。

  3. 睡眠:進(jìn)程正在睡眠無(wú)法運(yùn)行(“睡眠”狀態(tài)有兩種)。因?yàn)樗诘却粋€(gè)外部事件,調(diào)度器無(wú)法在任務(wù)切換時(shí)選擇該進(jìn)程。

  4. 僵尸:進(jìn)程已經(jīng)死亡,但是它的數(shù)據(jù)還沒有從進(jìn)程表中刪除。(在UNIX操作系統(tǒng)下銷毀進(jìn)程需要兩步,第一步由另一個(gè)進(jìn)程或一個(gè)用戶殺死(通過(guò)信號(hào)完成);第二步是進(jìn)程的父進(jìn)程在子進(jìn)程終止時(shí)必須調(diào)用或已經(jīng)調(diào)用wait4系統(tǒng)調(diào)用,使內(nèi)核釋放為子進(jìn)程保留的資源。當(dāng)條件一發(fā)生,第二個(gè)條件不成立的情況,便會(huì)出現(xiàn)“僵尸”狀態(tài))

  • 為了維持系統(tǒng)中現(xiàn)存的各個(gè)進(jìn)程,防止它們與系統(tǒng)其他部分相互干擾,Linux進(jìn)程管理結(jié)構(gòu)中還需要兩種進(jìn)程狀態(tài)選項(xiàng):用戶狀態(tài)和核心態(tài)。進(jìn)程通常處于用戶狀態(tài),只能訪問自身的數(shù)據(jù),無(wú)法干擾系統(tǒng)中其他進(jìn)程。如果進(jìn)程想要訪問系統(tǒng)數(shù)據(jù),則必須切換到核心態(tài),這種訪問必須經(jīng)由明確定義的路徑(系統(tǒng)調(diào)用)。從用戶狀態(tài)進(jìn)入核心態(tài)的第二種方法是通過(guò)中斷,此時(shí)切換是自動(dòng)觸發(fā)的,處理中斷操作,通常與中斷發(fā)生時(shí)執(zhí)行的程序無(wú)關(guān)。(系統(tǒng)調(diào)用是由用戶應(yīng)用程序有意調(diào)用的,中斷則是不可預(yù)測(cè)的)

  • 內(nèi)核的搶占調(diào)度模型是優(yōu)先讓優(yōu)先級(jí)高的進(jìn)程占用CPU,它建立了一個(gè)層次結(jié)構(gòu),用于判斷哪些進(jìn)程狀態(tài)可由其他狀態(tài)搶占。

  1. 普通進(jìn)程總是可能被搶占,甚至由其他進(jìn)程搶占。

  2. 如果系統(tǒng)處于核心態(tài)并正在處理系統(tǒng)調(diào)用,那么其他進(jìn)程是無(wú)法奪取CPU時(shí)間的。

  3. 中斷可以暫停處于用戶態(tài)和和心態(tài)的進(jìn)程,具有最高優(yōu)先級(jí)。

  • 在內(nèi)核2.5開發(fā)期間,內(nèi)核搶占(kernel preemption)選項(xiàng)被添加到內(nèi)核,它支持緊急情況下切換到另一個(gè)進(jìn)程,甚至當(dāng)前進(jìn)程處于系統(tǒng)調(diào)用也行。內(nèi)核搶占可以減少等待時(shí)間,但代價(jià)是增加了內(nèi)核的復(fù)雜度,因?yàn)閾屨紩r(shí)有許多數(shù)據(jù)結(jié)構(gòu)需要針對(duì)并發(fā)訪問進(jìn)行保護(hù)。

三、進(jìn)程表示

  • Linux內(nèi)核涉及進(jìn)程和程序的所有算法都圍繞數(shù)據(jù)結(jié)構(gòu)task_struct建立,該結(jié)構(gòu)定義在include/sched.h中。task_struct包含很多成員,將進(jìn)程與各內(nèi)核子系統(tǒng)聯(lián)系起來(lái)。task_struct定義的簡(jiǎn)化版本如下:

  • task_struct結(jié)構(gòu)體的內(nèi)容可以分解為各個(gè)部分,每個(gè)部分表示進(jìn)程的一個(gè)方面。

  • 狀態(tài)和執(zhí)行信息;

  • 有關(guān)已經(jīng)分配的虛擬內(nèi)存信息;

  • 進(jìn)程身份憑據(jù);

  • 使用的文件信息;

  • 線程信息記錄該進(jìn)程特定于CPU的運(yùn)行時(shí)間數(shù)據(jù)(與硬件無(wú)關(guān));

  • 與其他應(yīng)用程序協(xié)作時(shí)所需的進(jìn)程間通信相關(guān)信息;

  • 該進(jìn)程所用的信號(hào)處理程序,用于響應(yīng)信號(hào)的到來(lái)。

  • 對(duì)于進(jìn)程管理,task_struct中state指定了當(dāng)前狀態(tài)(TASK_RUNNING運(yùn)行;TASK_INTERRUPTIBLE等待某事件/資源的睡眠狀態(tài);TASK_UNINTERRUPTIBLE年內(nèi)和指示停用的睡眠狀態(tài);TASK_STOPPED特意停止運(yùn)行(多用于調(diào)試);TASK_TRACED(用于調(diào)試區(qū)分常規(guī)進(jìn)程);EXIT_ZOMBIE僵尸狀態(tài);EXIT_DEAD指wait系統(tǒng)調(diào)用已發(fā)出)。

  • 此外,Linux提供資源限制(resource limit)機(jī)制,對(duì)進(jìn)程使用系統(tǒng)資源施加某些限制。在task_struct中反應(yīng)在rlim數(shù)組上,系統(tǒng)調(diào)用setrlimit來(lái)增減當(dāng)前限制。rlim數(shù)組中的位置標(biāo)識(shí)了受限制資源的類型,這也是內(nèi)核需要定義預(yù)處理器常數(shù),將資源與位置關(guān)聯(lián)起來(lái)的原因。具體代碼以及不同硬件上的值的設(shè)置手冊(cè)上有詳細(xì)描述。init進(jìn)程的限制在系統(tǒng)啟動(dòng)時(shí)生效, 定義在include/asm-generic-resource.h中的INIT_RLIMITS。

  • 1、進(jìn)程類型

  • 典型的UNIX進(jìn)程包括:二進(jìn)制代碼組成的應(yīng)用程序、單線程、分配給應(yīng)用程序的一組資源。新進(jìn)程使用fork和exec系統(tǒng)調(diào)用產(chǎn)生。

  • fork生成當(dāng)前進(jìn)程一個(gè)相同副本,該副本稱為子進(jìn)程,子進(jìn)程復(fù)制所有父進(jìn)程的資源,父子進(jìn)程相互獨(dú)立。

  • exec從一個(gè)可執(zhí)行文件加載另一個(gè)應(yīng)用程序,來(lái)替代當(dāng)前運(yùn)行的程序。(不創(chuàng)建新進(jìn)程,必須首先使用fork復(fù)制一個(gè)舊進(jìn)程,然后調(diào)用exec在系統(tǒng)上創(chuàng)建另一個(gè)應(yīng)用程序)

  • 除此以外,Linux還提供了clone系統(tǒng)調(diào)用,用于實(shí)現(xiàn)線程,但僅僅系統(tǒng)調(diào)用還不足以做到,還需要用戶空間庫(kù)配合實(shí)現(xiàn)。

  • clone工作原理基本與fork相同,但新進(jìn)程不獨(dú)立于父進(jìn)程,而可以指定與父進(jìn)程共享某些資源。

  • 2、命名空間

  • 命名空間提供了虛擬化的一種輕量級(jí)形式,使得我們可以從不同方面查看運(yùn)行系統(tǒng)的全局屬性。傳統(tǒng)上,在Linux以及其它衍生的UNIX變體中,許多資源是全局管理的。系統(tǒng)中所有進(jìn)程都通過(guò)PID標(biāo)識(shí),內(nèi)核必須管理一個(gè)全局的PID列表,用戶ID的管理方式類似,通過(guò)全局唯一的UID標(biāo)識(shí)。全局ID使內(nèi)核可以有選擇允許或拒絕某些特權(quán),但不能阻止若干個(gè)用戶能看到彼此。如果Web主機(jī)打算向用戶提供計(jì)算機(jī)的全部訪問權(quán)限,傳統(tǒng)意義上需要為每個(gè)用戶提供一臺(tái)物理機(jī),使用KVM或VMWare時(shí)資源分配做得不是非常好。

  • 對(duì)于計(jì)算機(jī)的各個(gè)用戶都需要建立獨(dú)立內(nèi)核,和一份完全安裝好的配套用戶層應(yīng)用這個(gè)問題,命名空間提供了一種不同的解決方案。虛擬化系統(tǒng)中,一臺(tái)物理計(jì)算機(jī)可以運(yùn)行多個(gè)內(nèi)核,可能是并行的多個(gè)不同的操作系統(tǒng),命名空間只使用一個(gè)內(nèi)核在一臺(tái)物理機(jī)上運(yùn)作,將前述的所有資源通過(guò)命名空間抽象,使得可以將一組進(jìn)程放置到容器中,各個(gè)容器彼此隔離。


  • 圖3描述了命名空間可以組織為層次關(guān)系。一個(gè)命名空間是父命名空間,衍生了兩個(gè)子命名空間,子命名空間中各進(jìn)程擁有自己的PID號(hào)。雖然子容器不了解系統(tǒng)中其他容器,但父容器知道子命名空間的存在,也可以看到其中執(zhí)行的所有進(jìn)程,因此自子容器中的進(jìn)程可以映射到父容器中,獲取全局中唯一的PID號(hào)。若命名空間比較簡(jiǎn)單,也可以設(shè)計(jì)成非層次的(UTS命名空間,父子命名空間沒有聯(lián)系)。

  • 新的命名空間創(chuàng)建方式有兩種:fork或clone系統(tǒng)調(diào)用創(chuàng)建進(jìn)程時(shí),有特定選項(xiàng)可以控制是與父進(jìn)程共享命名空間,還是新建命名空間;unshare系統(tǒng)調(diào)用將進(jìn)程的某些部分從父進(jìn)程分離,其中也包括命名空間。 命名空間的實(shí)現(xiàn)分為兩個(gè)部分:每個(gè)子系統(tǒng)的命名空間結(jié)構(gòu);將給定進(jìn)程關(guān)聯(lián)到所屬各命名空間的機(jī)制。

  • 圖4是進(jìn)程與命名空間之間的聯(lián)系示意圖。


  • 子系統(tǒng)的全局屬性封裝到命名空間中,每個(gè)進(jìn)程關(guān)聯(lián)到選定的命名該空間。每個(gè)可以感知命名空間的內(nèi)核子系統(tǒng)都提供了一個(gè)數(shù)據(jù)結(jié)構(gòu)struct_nsproxy(匯集了指向特定于子系統(tǒng)的命名空間包裝器的指針),將所有通過(guò)命名空間形式提供的對(duì)象集中起來(lái)。

  • 每個(gè)命名空間都提供了相應(yīng)的標(biāo)志用于fork建立一個(gè)新的命名空間。因?yàn)樵诿總€(gè)進(jìn)程關(guān)聯(lián)到自身命名空間時(shí),使用了指針,所以多個(gè)進(jìn)程可以共享一組子命名空間,修改給定的命名空間,對(duì)所有屬于該命名空間的進(jìn)程都是可見的。

  • UTS(UNIX Timesharing System)命名空間

  • 它存儲(chǔ)了系統(tǒng)的名稱(Linux...)、內(nèi)核發(fā)布版本、機(jī)器名等。使用uname工具可以取得這些屬性的當(dāng)前值。它幾乎不需要特別處理,因?yàn)樗恍枰?jiǎn)單量,沒有層次組織。所有相關(guān)信息都匯集到結(jié)構(gòu)uts_namespace中。

  • 內(nèi)核通過(guò)copy_utsname函數(shù)創(chuàng)建UTS命名空間,在讀取或設(shè)置UTS屬性值時(shí),內(nèi)核會(huì)保證總是操作特定于當(dāng)前進(jìn)程的uts_namespace實(shí)例,在當(dāng)前進(jìn)程修改UTS屬性不會(huì)反映到父進(jìn)程,而父進(jìn)程的修改也不會(huì)傳播到子進(jìn)程。

用戶命名空間

  • 用戶命名空間維護(hù)了一些統(tǒng)計(jì)數(shù)據(jù)(如進(jìn)程和打開文件數(shù)目),它在數(shù)據(jù)結(jié)構(gòu)管理方面類似于UTS,在要求創(chuàng)建新的用戶命名空間時(shí),生成當(dāng)前用戶命名空間的一份副本,并關(guān)聯(lián)到當(dāng)前進(jìn)程nsproxy實(shí)例。

  • 每個(gè)用戶命名空間對(duì)其用戶資源使用的統(tǒng)計(jì),與其他命名空間完全無(wú)關(guān),對(duì)root用戶的統(tǒng)計(jì)也是如此。這是因?yàn)樵诳寺∫粋€(gè)用戶命名空間時(shí),為當(dāng)前用戶和root都創(chuàng)建了新的user_struct實(shí)例。

3、進(jìn)程ID號(hào)

  • UNIX進(jìn)程會(huì)分配一個(gè)ID號(hào)(簡(jiǎn)稱PID)作為其命名空間中唯一的標(biāo)識(shí)。ID有的多類型:

  1. 進(jìn)程處于某個(gè)線程組時(shí),擁有線程組ID(TGID)(若進(jìn)程沒有使用線程,則PID與TGID相同);

  2. 獨(dú)立進(jìn)程可以合并成進(jìn)程組,進(jìn)程組成員的task_struct的pgrp屬性值相同(為進(jìn)程組組長(zhǎng)PID)(用管道連接的進(jìn)程便包含在同一個(gè)進(jìn)程組中);

  3. 幾個(gè)進(jìn)程組可以合并成一個(gè)會(huì)話,會(huì)話中所有進(jìn)程都有會(huì)話ID(SID),保存在task_struct的session中。

  • 命名空間增加了PID管理的復(fù)雜性。PID命名空間按層次組織,因此必須區(qū)分局部ID和全局ID。

  1. 全局ID是在內(nèi)核本身和初始命名空間中唯一的ID號(hào),對(duì)每個(gè)ID類型,都有一個(gè)全局ID,保證在整個(gè)系統(tǒng)中唯一;

  2. 局部ID屬于某特定命名空間,不具備全局有效性。在所屬的命名空間內(nèi)部有效,因此類型相同、值也相同的ID可能出現(xiàn)在不同的命名空間中。

  • PID分配器(pid allocator)用于加速新ID的分配(此處ID是廣義的包括TGID,SID等)。內(nèi)核提供輔助函數(shù),實(shí)現(xiàn)通過(guò)ID及其類型查找進(jìn)程的task_struct的功能,以及將ID的內(nèi)核表示形式和用戶空間可見的數(shù)值進(jìn)行轉(zhuǎn)換的功能。

  • PID命名空間的表示方式以及含義:

PID的管理圍繞struct_pid和struct_upid展開,struct pid是內(nèi)核對(duì)PID的內(nèi)部表示,而struct upid則表示特定的命名空間中可見的信息。

  • 枚舉類型中定義的ID類型不包括線程組ID,因?yàn)榫€程組ID無(wú)非是線程組組長(zhǎng)的PID。

  • 圖5對(duì)pid和upid兩個(gè)結(jié)構(gòu)的關(guān)系進(jìn)行了概述。對(duì)于members數(shù)組,形式上只有一個(gè)數(shù)組項(xiàng),如果一個(gè)進(jìn)程只包含在全局命名空間中,那么確實(shí)如此。由于該數(shù)組位于結(jié)構(gòu)的末尾,因此只要分配更多的內(nèi)存空間,即可向數(shù)組添加附加的項(xiàng)。


  • 內(nèi)核提供了若干輔助函數(shù),用于操作和掃描上述復(fù)雜結(jié)構(gòu),完成以下兩個(gè)任務(wù):

  1. 給出局部數(shù)字id和對(duì)應(yīng)的命名空間,查找此二元組的task_struct;

  2. 給出task_struct、id類型、命名空間,取得命名空間局部的數(shù)字ID。

  • 此外,內(nèi)核還負(fù)責(zé)提供機(jī)制來(lái)生成唯一PID,具體方法:為跟蹤已經(jīng)分配和仍然可用的PID,內(nèi)核使用一個(gè)大的位圖,其中每個(gè)PID由一個(gè)比特標(biāo)識(shí)。PID的值可通過(guò)對(duì)應(yīng)比特在位圖中的位置計(jì)算而來(lái)。所有其他的ID都可以派生自PID。

4、進(jìn)程關(guān)系

  • 完成了ID連接關(guān)系之后,內(nèi)核還負(fù)責(zé)管理建立在UNIX進(jìn)程創(chuàng)建模型之上的“家族關(guān)系”(如果由進(jìn)程A形成了進(jìn)程B,則A是父進(jìn)程,B是子進(jìn)程;若進(jìn)程A形成了若干個(gè)子進(jìn)程,則這些子進(jìn)程之間成為兄弟關(guān)系)。

  • 圖6說(shuō)明了進(jìn)程家族中的父子關(guān)系和兄弟關(guān)系,以及task_struct中children和sibling兩個(gè)鏈表表頭實(shí)現(xiàn)這些關(guān)系的方式。


四、進(jìn)程管理相關(guān)的系統(tǒng)調(diào)用

1、進(jìn)程復(fù)制

  • Linux的進(jìn)程復(fù)制有三種方式:

  1. fork,重量級(jí)調(diào)用,它建立了父進(jìn)程的完整副本,然后作為子進(jìn)程執(zhí)行。(為了減少工作量,提高效率,使用了寫時(shí)復(fù)制技術(shù))

  2. vfork,類似于fork,不創(chuàng)建父進(jìn)程副本。相反,父子進(jìn)程之間共享數(shù)據(jù)。(節(jié)省了大量CPU時(shí)間)vfork設(shè)計(jì)用于子進(jìn)程形成后立即執(zhí)行execve系統(tǒng)調(diào)用加載新程序的情形。在子進(jìn)程退出或開始 新程序之前,內(nèi)核保證父進(jìn)程處于堵塞狀態(tài)。

  3. clone,產(chǎn)生線程,可以對(duì)父子進(jìn)程之間的共享、復(fù)制進(jìn)行精確控制。

  • (1)寫時(shí)復(fù)制(COW)

  • 寫時(shí)復(fù)制技術(shù)(copy-on-write),用來(lái)防止在fork執(zhí)行時(shí)將父進(jìn)程的所有數(shù)據(jù)復(fù)制到子進(jìn)程。為了解決很多情況下不需要復(fù)制父進(jìn)程信息時(shí),復(fù)制父進(jìn)程副本使用大量?jī)?nèi)存,耗費(fèi)很長(zhǎng)時(shí)間的問題。 fork之后,父子進(jìn)程的地址空間指向同樣的物理內(nèi)存頁(yè),此時(shí),物理內(nèi)存頁(yè)處于只讀狀態(tài)。如果確實(shí)要對(duì)內(nèi)存進(jìn)行寫入操作,會(huì)產(chǎn)生缺頁(yè)異常,然后由內(nèi)核分配內(nèi)存空間。

  • (2)執(zhí)行系統(tǒng)調(diào)用

  • fork、vfork和clone系統(tǒng)調(diào)用的入口點(diǎn)分別是sys_fork、sys_vfork和sys_clone函數(shù)。這些入口函數(shù)都調(diào)用體系結(jié)構(gòu)無(wú)關(guān)的do_fork函數(shù),通過(guò)clone_flags這個(gè)標(biāo)志集合區(qū)分不同入口。

  • (3)do_fork的實(shí)現(xiàn)

  • do_fork的代碼流程圖如圖7所示。


  • 子進(jìn)程生產(chǎn)成功后,內(nèi)核必須執(zhí)行收尾操作:

  • 如果設(shè)置了CLONE_PID標(biāo)志,fork操作可能會(huì)創(chuàng)建新的pid命名空間。如果創(chuàng)建了新的命名空間,則需要在新命名空間獲取pid,否則直接獲取局部pid。

  • 如果用了ptrace監(jiān)控,創(chuàng)建進(jìn)程后,就向它發(fā)送SIGSTOP信號(hào),讓調(diào)試器檢查數(shù)據(jù)。

  • 子進(jìn)程使用wake_up_new_task喚醒(將它的task_struct添加到調(diào)度器隊(duì)列,讓它有機(jī)會(huì)執(zhí)行)。

  • 如果使用vfork機(jī)制,必須啟用子進(jìn)程的完成機(jī)制,子進(jìn)程的task_struct的vfork_done成員即用于該目的,父進(jìn)程用wait_for_completion函數(shù)在該變量中進(jìn)入睡眠,直至子進(jìn)程退出。子進(jìn)程終止時(shí),內(nèi)核調(diào)用complete(vfork_done)喚醒因該變量睡眠的進(jìn)程。

  • (4)復(fù)制進(jìn)程

  • 在do_fork中大多數(shù)工作是由copy_process函數(shù)完成的,該函數(shù)根據(jù)標(biāo)志的控制,處理了3個(gè)系統(tǒng)調(diào)用(fork、vfork和clone)的主要工作。

  • copy_process流程圖如圖8所示。(詳見手冊(cè))


  • 5)創(chuàng)建線程特別問題

  • 用戶空間線程庫(kù)使用clone系統(tǒng)調(diào)用來(lái)生成新線程。該調(diào)用支持(上文討論之外的)標(biāo)志,對(duì)copy_process(及其調(diào)用的函數(shù))具有某些特殊影響。

  • CLONE_PARENT_SETTID將生成線程的PID復(fù)制到clone調(diào)用指定的用戶空間中的某個(gè)地址

  • CLONE_CHILD_SETTID首先會(huì)將另一個(gè)傳遞到clone的用戶空間指針(child_tidptr)保存在新進(jìn)程的task_struct中。

  • CLONE_CHILD_CLEARTID首先會(huì)在copy_process中將用戶空間指針child_tidptr保存在task_struct中,這次是另一個(gè)不同的成員。

  • 上述標(biāo)志可用于從用戶空間檢測(cè)內(nèi)核中線程的產(chǎn)生和銷毀。CLONE_CHILD_SETTID和CLONE_PARENT_SETTID用于檢測(cè)線程的生成。CLONE_CHILD_CLEARTID用于在線程結(jié)束時(shí)從內(nèi)核向用戶空間傳遞信息,在多處理器系統(tǒng)上這些檢測(cè)可以真正地并行執(zhí)行。

  • 2、內(nèi)核線程

  • 內(nèi)核線程是直接由內(nèi)核本身啟動(dòng)的進(jìn)程。內(nèi)核線程實(shí)際上是將內(nèi)核函數(shù)委托給獨(dú)立的進(jìn)程,與系統(tǒng)中其他進(jìn)程“并行”執(zhí)行(實(shí)際上,也并行于內(nèi)核自身的執(zhí)行)。內(nèi)核線程經(jīng)常稱之為(內(nèi)核)守護(hù)進(jìn)程,它們用于執(zhí)行下列任務(wù):

  • 周期性地將修改的內(nèi)存頁(yè)與頁(yè)來(lái)源塊設(shè)備同步(例如,使用mmap的文件映射)。

  • 如果內(nèi)存頁(yè)很少使用,則寫入交換區(qū)。

  • 管理延時(shí)動(dòng)作(deferred action)。

  • 實(shí)現(xiàn)文件系統(tǒng)的事務(wù)日志。

  • 基本上,內(nèi)核線程有兩種:

  • 線程啟動(dòng)后一直等待,直至內(nèi)核請(qǐng)求線程執(zhí)行某一特定操作。

  • 線程啟動(dòng)后按周期性間隔運(yùn)行,檢測(cè)特定資源的使用,在用量超出或低于預(yù)置的限制值時(shí)采取行動(dòng)。內(nèi)核使用這類線程用于連續(xù)監(jiān)測(cè)任務(wù)。

  • 因?yàn)閮?nèi)核線程是由內(nèi)核自身生成的,它有兩個(gè)特別之處:

  • 它們?cè)贑PU的管態(tài)(supervisor mode)執(zhí)行,而不是用戶狀態(tài)。

  • 它們只可以訪問虛擬地址空間的內(nèi)核部分(高于TASK_SIZE的所有地址),但不能訪問用戶空間。

  • 內(nèi)核線程可以用兩種方法實(shí)現(xiàn):

  • 古老的方法:

  • 將一個(gè)函數(shù)傳遞給kernel_thread,內(nèi)核調(diào)用daemonize以轉(zhuǎn)換為守護(hù)進(jìn)程,從內(nèi)核釋放父進(jìn)程的所有資源。

  • daemonize阻塞信號(hào)的接收。

  • 將init作為守護(hù)進(jìn)程的父進(jìn)程。

  • 備選方案:使用宏kthread_run(參數(shù)與kthread_create相同),它會(huì)調(diào)用kthread_create創(chuàng)建新線程,立即喚醒它。還可以使用kthread_create_cpu代替kthread_create創(chuàng)建內(nèi)核線程,使之綁定到特定的CPU。

  • 3、啟動(dòng)新程序

  • (1)execve的實(shí)現(xiàn)

  • 該系統(tǒng)調(diào)用的入口點(diǎn)是體系結(jié)構(gòu)相關(guān)的sys_execve函數(shù)。該函數(shù)很快將其工作委托給系統(tǒng)無(wú)關(guān)的do_execve例程。

  • do_execve的代碼流程圖如圖9所示。

  • 編輯

  • do_execve的主要工作:

  • 打開要執(zhí)行的文件;

  • bprm_init,申請(qǐng)進(jìn)程空間并初始化,處理若干管理性任務(wù);

  • prepare_binprm,提供父進(jìn)程相關(guān)的值(特別是有效UID和GID),也是用于初始化;

  • search_binary_handler,查找一種適當(dāng)?shù)亩M(jìn)制格式,用于所要執(zhí)行的特定文件。

  • 通常,二進(jìn)制格式處理程序執(zhí)行下列操作:

  • 釋放原進(jìn)程的所有資源;

  • 將應(yīng)用程序映射到虛擬地址空間,參數(shù)和環(huán)境也映射到虛擬地址空間;

  • 設(shè)置進(jìn)程的指令指針和其他特定于體系結(jié)構(gòu)的寄存器。

  • (2)解釋二進(jìn)制格式

  • Linux內(nèi)核中,每種二進(jìn)制格式都表示為結(jié)構(gòu)體linux_binfmt,都需要用register_binfmt向內(nèi)核注冊(cè)。

  • linux_binfmt結(jié)構(gòu)為:

  • 二進(jìn)制格式主要接口函數(shù)

  • load_binary用于加載普通程序。

  • load_shlib用于加載共享庫(kù),即動(dòng)態(tài)庫(kù)。

  • core_dump用于在程序錯(cuò)誤的情況下輸出內(nèi)存轉(zhuǎn)儲(chǔ),用于調(diào)試分析,以解決問題。

  • 4、退出進(jìn)程

  • 進(jìn)程必須用exit系統(tǒng)調(diào)用終止,使得內(nèi)核有機(jī)會(huì)將該進(jìn)程使用的資源釋放回系統(tǒng)。該調(diào)用的入口點(diǎn)是sys_exit函數(shù),該函數(shù)的實(shí)現(xiàn)就是將各個(gè)引用計(jì)數(shù)器減1,如果引用計(jì)數(shù)器歸0而沒有進(jìn)程再使用對(duì)應(yīng)的結(jié)構(gòu),那么將相應(yīng)的內(nèi)存區(qū)域返還給內(nèi)存管理模塊.






Linux內(nèi)核架構(gòu)分析--進(jìn)程管理及調(diào)度學(xué)習(xí)筆記(詳細(xì)記錄)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
祥云县| 建平县| 婺源县| 河北省| 霍山县| 泰来县| 昌黎县| 九江市| 新巴尔虎左旗| 南安市| 神池县| 崇明县| 廊坊市| 富裕县| 德庆县| 修水县| 江城| 忻城县| 赣榆县| 宜君县| 高安市| 且末县| 钦州市| 长治市| 屏东市| 临清市| 中宁县| 赣州市| 大厂| 锡林浩特市| 江城| 北辰区| 临漳县| 八宿县| 阜城县| 淳化县| 武强县| 出国| 天峨县| 甘泉县| 浑源县|