進程原理及系統(tǒng)調(diào)用
操作系統(tǒng)作為硬件的使用層,提供使用硬件資源的能力,進程作為操作系統(tǒng)使用層, 提供使用操作系統(tǒng)抽象出的資源層的能力。進程:是指計算機中已運行的程序。進程本身不是基本的運行單位,而是線程的容器。 程序本身只是指令、數(shù)據(jù)及其組織形式的描述,進程才是程序(那些指令和數(shù)據(jù))的真正運行實例。
進程是處于執(zhí)行時期的程序。
內(nèi)核調(diào)度的對象是線程,不是進程。
1.1 進程四要素與線程區(qū)別
有一段程序代其執(zhí)行;
有進程專用的系統(tǒng)堆??臻g;
在內(nèi)核有task_struct數(shù)據(jù)結(jié)構(gòu);
進程有獨立的存儲空間,擁有專有的用戶空間;如果具備前面三條而缺少第四條,那就稱為"線程"。如果完全沒有用戶空間,那就稱為"內(nèi)核線程";如果共享用戶空間則就稱為"用戶線程"。
2.進程生命周期
Linux操作系統(tǒng)屬于多任務(wù)操作系統(tǒng),系統(tǒng)中的每個進程能夠分時復(fù)用CPU時間片,通過有效的進程調(diào)度策略實現(xiàn)多任務(wù)并行執(zhí)行。而進程在被CPU調(diào)度運行,等待CPU資源分配以及等待外部事件時會屬于不同的狀態(tài)。進程之間的狀態(tài)關(guān)系:運行 :該進程此刻正在執(zhí)行。等待:進程能夠運行,但沒有得到許可,因為CPU分配給另一個進程。調(diào)度器可以在 下一次任務(wù)切換時選擇該進程。睡眠 :進程正在睡眠無法運行,因為它在等待一個外部事件。調(diào)度器無法在下一次任 務(wù)切換時選擇該進程。
【進程狀態(tài)之間轉(zhuǎn)換】如下:

3.task_struct數(shù)據(jù)結(jié)構(gòu)
Linux內(nèi)核涉及進程和程序的所有算法都圍繞一個名為task_struct的數(shù)據(jù)結(jié)構(gòu)建立,該結(jié)構(gòu)定義在include/linux/sched.h中。這是系統(tǒng)中主要的一個結(jié)構(gòu)。在闡述調(diào)度器的實現(xiàn)之前,了解一下Linux管理進程的方式是很有必要的。 task_struct包含很多成員,將進程與各個內(nèi)核子系統(tǒng)聯(lián)系,task_struct定義如下:

4.進程優(yōu)先級
并非所有進程都具有相同的重要性。除了大多數(shù)我們所熟悉的進程優(yōu)先級之外,進程 還有不同的關(guān)鍵度類別,以滿足不同需求。首先進行比較粗糙的劃分,進程可以分為實時進程 和非實時進程(普通進程)。 實時進程優(yōu)先級(0-99)都比普通 進程的優(yōu)先級(100-139)高。當(dāng)系統(tǒng)中有實時進程 運行時,普通進程幾乎無法分到趕時間片(只能分到5%的CPU時間)。
5.進程系統(tǒng)調(diào)用
討論fork和exec系列系統(tǒng)調(diào)用的實現(xiàn)。通常這些調(diào)用不是由應(yīng)用程序直接發(fā)出的,而是通過一個中間層調(diào)用,即負責(zé)與內(nèi)核通信的C標(biāo)準(zhǔn)庫。從用戶狀態(tài)切換到核心態(tài)的方法,依不同的體系結(jié)構(gòu)而各有不同。

5.1 進程復(fù)制
傳統(tǒng)的UNIX中用于復(fù)制進程的系統(tǒng)調(diào)用是fork。但它并不是Linux為此實現(xiàn)的唯一調(diào)用, 實際上Linux實現(xiàn)了3個(1) fork是重量級調(diào)用,因為它建立了父進程的一個完整副本,然后作為子進程執(zhí)行。 為減少與該調(diào)用相關(guān)的工作量,Linux使用了寫時復(fù)制(copy-on-write)技術(shù)。(2) vfork類似于fork,但并不創(chuàng)建父進程數(shù)據(jù)的副本。相反,父子進程之間共享數(shù)據(jù)。 這節(jié)省了大量CPU時間(如果一個進程操縱共享數(shù)據(jù),則另一個會自動注意到)。(3) clone產(chǎn)生線程,可以對父子進程之間的共享、復(fù)制進行精確控制。

只有在不得不復(fù)制數(shù)據(jù)內(nèi)容時才去復(fù)制數(shù)據(jù)內(nèi)容,這就是寫時復(fù)制核心思想,可以看到因為修改頁Z導(dǎo)致子進程不得不去復(fù)制原頁Z來保證父子進程互不干擾內(nèi)核只為新生成的子進程創(chuàng)建虛擬空間結(jié)構(gòu),它們來復(fù)制于父進程的虛擬結(jié)構(gòu),但是不為這些分配物理內(nèi)存,它們共享父進程的物理空間,當(dāng)父進程中有更改相應(yīng)段的行為發(fā)生時,再為子進程相應(yīng)段分配物理空間
【寫時復(fù)制】內(nèi)核使用了寫時復(fù)制(Copy-On-Write,COW)技術(shù),以防止在fork執(zhí)行時將父進程的所有數(shù)據(jù) 復(fù)制到子進程。在調(diào)用fork時,內(nèi)核通常對父進程的每個內(nèi)存頁,都為子進程創(chuàng)建一個相同的副本。【執(zhí)行系統(tǒng)調(diào)用】fork、vfork和clone系統(tǒng)調(diào)用的入口點分別是sys_fork、sys_vfork和sys_clone函數(shù)。其定義依賴于 具體的體系結(jié)構(gòu),因為在用戶空間和內(nèi)核空間之間傳遞參數(shù)的方法因體系結(jié)構(gòu)而異。【do_fork實現(xiàn)】所有3個fork機制最終都調(diào)用kernel/fork.c中的do_fork(一個體系結(jié)構(gòu)無關(guān)的函數(shù)),其代碼流程 如圖所示。


5.2 內(nèi)核線程
內(nèi)核線程是直接由內(nèi)核本身啟動的進程。內(nèi)核線程實際上是將內(nèi)核函數(shù)委托給獨立的進程,與系統(tǒng)中其他進程“并行”執(zhí)行(實際上,也并行于內(nèi)核自身的執(zhí)行)。內(nèi)核線程經(jīng)常稱之為(內(nèi)核)守護進程。它們用于執(zhí)行下列任務(wù)。? 周期性地將修改的內(nèi)存頁與頁來源塊設(shè)備同步(例如,使用mmap的文件映射)。? 如果內(nèi)存頁很少使用,則寫入交換區(qū)。? 管理延時動作(deferred action)。? 實現(xiàn)文件系統(tǒng)的事務(wù)日志。
5.3 退出進程
進程必須用exit系統(tǒng)調(diào)用終止。這使得內(nèi)核有機會將該進程使用的資源釋放回系統(tǒng)。見kernel/exit.c------>do_exit。簡而言之, 該函數(shù)的實現(xiàn)就是將各個引用計數(shù)器減1,如果引用計數(shù)器歸0而 沒有進程再使用對應(yīng)的結(jié)構(gòu),那么將相應(yīng)的內(nèi)存區(qū)域返還給內(nèi)存管理模塊。
