進(jìn)程優(yōu)先級(jí)
進(jìn)程可以分為實(shí)時(shí)進(jìn)程和非實(shí)時(shí)進(jìn)程。
- 硬實(shí)時(shí)進(jìn)程有嚴(yán)格的時(shí)間限制,某些任務(wù)必須在指定的時(shí)限內(nèi)完成。這類進(jìn)程的關(guān)鍵特征是使進(jìn)程在可保證的時(shí)間范圍內(nèi)得到處理。linux在主流的內(nèi)核中不支持硬實(shí)時(shí)處理。
- 軟實(shí)時(shí)進(jìn)程時(shí)間限制沒(méi)有像硬實(shí)時(shí)進(jìn)程一樣那么嚴(yán)格,可以稍微晚一點(diǎn)。
- 普通進(jìn)程沒(méi)有時(shí)間限制,但也可以根據(jù)重要性分配優(yōu)先級(jí)。
在搶占式多任務(wù)處理中,每個(gè)進(jìn)程都會(huì)分配到一定時(shí)間去執(zhí)行,當(dāng)時(shí)間到期后會(huì)被內(nèi)核收回控制權(quán)讓別的進(jìn)程運(yùn)行,其運(yùn)行環(huán)境如寄存器內(nèi)容和頁(yè)表會(huì)被保存起來(lái),在之后對(duì)進(jìn)程環(huán)境可完全恢復(fù)。
進(jìn)程的幾種狀態(tài):

- 如果進(jìn)程必須等待一個(gè)事件發(fā)生,狀態(tài)從運(yùn)行到睡眠(或者叫阻塞)。
- 如果進(jìn)程等待的事件發(fā)生了,狀態(tài)從睡眠到等待(或者叫就緒)。
- 當(dāng)進(jìn)程被授予CPU事件后,狀態(tài)就從等待到運(yùn)行。
- 當(dāng)進(jìn)程調(diào)度器從該進(jìn)程收回CPU資源時(shí),狀態(tài)就從運(yùn)行到等待。
- 當(dāng)進(jìn)程執(zhí)行終止,狀態(tài)從運(yùn)行到終止。
在task_struct的成員state中指明了進(jìn)程的當(dāng)前狀態(tài),可選用值:
- TASK_RUNNING 進(jìn)程處于可運(yùn)行狀態(tài),確保進(jìn)程可以立即執(zhí)行(等待)
- TASK_INTERRUPTIBLE 進(jìn)程在等待事件或者其他資源時(shí)的睡眠狀態(tài)。
- TASK_STOPPED表示進(jìn)程特意(如調(diào)試器暫停)停止運(yùn)行。
- TASK_TRACED
- EXIT_ZOMBIE 僵尸狀態(tài)
- EXIT_DEAD
當(dāng)進(jìn)程終止時(shí),父進(jìn)程必須調(diào)用wait系統(tǒng)調(diào)用,使得內(nèi)核可以釋放子進(jìn)程保留的資源。否則會(huì)產(chǎn)生僵尸進(jìn)程。
用戶態(tài)和核心態(tài)
進(jìn)程通常處于用戶態(tài),只能訪問(wèn)自身的數(shù)據(jù),不會(huì)干擾也不會(huì)察覺(jué)到系統(tǒng)的其他進(jìn)程。如果進(jìn)程想訪問(wèn)系統(tǒng)數(shù)據(jù)和功能,那就必須轉(zhuǎn)換為核心態(tài),一種方法是系統(tǒng)調(diào)用,另一種方法是中斷。系統(tǒng)調(diào)用是程序主動(dòng)的,中斷是不可預(yù)測(cè)的。處理中斷的操作一般與正在執(zhí)行的進(jìn)程無(wú)關(guān),例如進(jìn)入系統(tǒng)的網(wǎng)絡(luò)數(shù)據(jù)包是通過(guò)中斷通知,但當(dāng)前運(yùn)行的進(jìn)程不會(huì)察覺(jué)。因?yàn)橹袛嘤|發(fā)后需要快速處理,所以中斷具有最高級(jí)別,可以暫停處于用戶態(tài)和核心態(tài)的進(jìn)程。
若系統(tǒng)處于核心態(tài)并處理系統(tǒng)調(diào)用,那么其他進(jìn)程是無(wú)法奪取CPU資源的(中斷可以)。
Linux提供資源限制機(jī)制,對(duì)進(jìn)程使用系統(tǒng)資源施加限制。是task_struct中的rlim數(shù)組。其數(shù)據(jù)項(xiàng)為rlimit
<resource.h>
struct rlimit{
unsigned long rlim_cur;
unsigned long rlim_max;
}
rlim_cur是進(jìn)程在當(dāng)前的資源限制,稱為軟限制。
rlim_max是該限制的最大容許值,稱為硬限制。
系統(tǒng)調(diào)用setrlimit來(lái)增減當(dāng)前限制,但不能超出rlim_max指定的值。(可以通過(guò)setrlimit手冊(cè)頁(yè)來(lái)看詳情限制。)
在Linux中,很多資源是全局的。如所有進(jìn)程都是用PID標(biāo)識(shí)的,所以內(nèi)核必須管理一個(gè)全局PID列表。
命名空間建立了系統(tǒng)的不同視圖

心動(dòng)命名空間可以用兩種方式創(chuàng)建:
- 用fork或clone系統(tǒng)調(diào)用創(chuàng)建新進(jìn)程時(shí)。
- unshare系統(tǒng)調(diào)用將進(jìn)程的某些部分從父進(jìn)程分離。
進(jìn)程ID
線程組ID,處于某個(gè)線程組的所有進(jìn)程有統(tǒng)一的線程ID(TGID)。若進(jìn)程沒(méi)有使用線程,那么PID和TGID相同。
進(jìn)程組ID,獨(dú)立進(jìn)程可以合并為進(jìn)程組,進(jìn)程組的pgrp屬性值都是相同的,為進(jìn)程組組長(zhǎng)的PID。
會(huì)話,幾個(gè)進(jìn)程組可以合并為一個(gè)會(huì)話,會(huì)話中所有進(jìn)程都有相同的會(huì)話ID,保存在task_struct的session成員中。
全局ID:是在內(nèi)核本身和初始命名空間中唯一的ID號(hào),在整個(gè)系統(tǒng)中是唯一的。
局部ID:屬于某個(gè)特定的命名空間,不具備全局有效性,只在所屬的命名空間內(nèi)。
全局PID和TGID直接保存在task_struct中,都是為_(kāi)_kernel_pid_t類型。會(huì)話和進(jìn)程組ID直接保存在用于信號(hào)處理的結(jié)構(gòu)中。
進(jìn)程復(fù)制
- fork是重量級(jí)調(diào)用,建立了父進(jìn)程的一個(gè)完整副本,然后作為子進(jìn)程執(zhí)行。為了減少調(diào)用的相關(guān)工作量,Linux使用了寫(xiě)時(shí)復(fù)制技術(shù)。
- vfork并不創(chuàng)建父進(jìn)程的副本,父子進(jìn)程之間共享數(shù)據(jù),在子進(jìn)程退出或開(kāi)始新程序之前,內(nèi)核保證父進(jìn)程處于堵塞狀態(tài)。
- clone產(chǎn)生線程。
在調(diào)用fork時(shí),內(nèi)核若對(duì)父進(jìn)程的每個(gè)內(nèi)存頁(yè)都創(chuàng)建一個(gè)相同的副本,這會(huì)使用掉大量?jī)?nèi)存也會(huì)在復(fù)制操作上消耗大量時(shí)間。內(nèi)核可以先只是復(fù)制父進(jìn)程頁(yè)表,采用寫(xiě)時(shí)復(fù)制技術(shù)。
fork,vfork,clone的系統(tǒng)調(diào)用入口點(diǎn)分別是sys_fork,sys_vfork,sys_clone。
Linux提供的execve系統(tǒng)調(diào)用用于新代碼替換現(xiàn)存程序,啟動(dòng)新程序。該系統(tǒng)調(diào)用點(diǎn)是sys_execve函數(shù)。
內(nèi)存中保存了進(jìn)程的唯一描述,并使用若干數(shù)據(jù)結(jié)構(gòu)與其他進(jìn)程連接起來(lái)。調(diào)度器需要完成的是調(diào)度策略和上下文切換。在多處理器系統(tǒng)上要避免調(diào)度器自相干擾。