實驗
準備環(huán)境

進行調(diào)試



進程上下文切換相關代碼分析
#define switch_to(prev, next, last)
do {
/*
* Context-switching clobbers all registers, so we clobber
* them explicitly, via unused output variables.
* (EAX and EBP is not listed because EBP is saved/restored
* explicitly for wchan access and EAX is the return value of
* __switch_to())
*/
unsigned long ebx, ecx, edx, esi, edi;
asm volatile("pushfl\n\t" /* save flags */
"pushl %%ebp\n\t" /* save EBP */
"movl %%esp,%[prev_sp]\n\t" /* save ESP */
"movl %[next_sp],%%esp\n\t" /* restore ESP */
"movl $1f,%[prev_ip]\n\t" /* save EIP */
"pushl %[next_ip]\n\t" /* restore EIP */
__switch_canary
"jmp __switch_to\n" /* regparm call */
"1:\t"
"popl %%ebp\n\t" /* restore EBP */
"popfl\n" /* restore flags */
/* output parameters */
: [prev_sp] "=m" (prev->thread.sp),
[prev_ip] "=m" (prev->thread.ip),
"=a" (last),
/* clobbered output registers: */
"=b" (ebx), "=c" (ecx), "=d" (edx),
"=S" (esi), "=D" (edi)
__switch_canary_oparam
/* input parameters: */
: [next_sp] "m" (next->thread.sp),
[next_ip] "m" (next->thread.ip),
/* regparm parameters for __switch_to(): */
[prev] "a" (prev),
[next] "d" (next)
__switch_canary_iparam
: /* reloaded segment registers */
"memory");
} while (0)
分析switch_to中的匯編代碼:
-保存flags
-保存esp
-重置esp
-保存eip
-重置eip
-轉(zhuǎn)跳至__switch_to
-恢復ebp
-恢復flags
為了控制進程的執(zhí)行,內(nèi)核必須有能力掛起正在CPU上執(zhí)行的進程,并恢復以前掛起的某個進程的執(zhí)行,這叫做進程切換、任務切換、上下文切換;
掛起正在CPU上執(zhí)行的進程,與中斷時保存現(xiàn)場是不同的,中斷前后是在同一個進程上下文中,只是由用戶態(tài)轉(zhuǎn)向內(nèi)核態(tài)執(zhí)行;
進程上下文包含了進程執(zhí)行需要的所有信息
-用戶地址空間:?包括程序代碼,數(shù)據(jù),用戶堆棧等
-控制信息?:進程描述符,內(nèi)核堆棧等
-硬件上下文(注意中斷也要保存硬件上下文只是保存的方法不同)
分析總結
不同類型的進程有不同的調(diào)度需求
-I/O-bound
--頻繁的進行I/O
--通常會花費很多時間等待I/O操作的完成
-CPU-bound
--計算密集型
--需要大量的CPU時間進行運算
需要不同的算法來使得系統(tǒng)運行更加高效,將CPU資源得到最大限度的使用
-批處理進程batch process
--不必與用戶交互,通常在后臺運行
--不必很快響應
--典型的批處理程序:編譯程序、科學計算
-實時進程real-time process
--有實時需求,不應被低優(yōu)先級的進程阻塞
--響應時間要短、要穩(wěn)定
--典型的實時進程:視頻、音頻、機械控制等
-交互式進程interactive process
--需要經(jīng)常與用戶交互,因此要花很多時間等待用戶輸入操作
--響應時間要快,平均延遲要低于50~150ms
--典型交互式程序:shell、文本編輯器、圖形應用程序等
有不同的需求應用存在,就需要有不同的調(diào)度應用策略
調(diào)度策略是一組規(guī)則,決定什么時候以怎樣的方式選擇一個新進程運行
linux的調(diào)度基于分時和優(yōu)先級
linux在不同版本更新,調(diào)度策略發(fā)生了不同的變化
-linux的進程根據(jù)優(yōu)先級排隊,根據(jù)特定的算法計算出進程的優(yōu)先級,用一個值表示把進程如何適當?shù)姆峙浣oCPU
-linux中進程的優(yōu)先級是動態(tài)的,調(diào)度程序會根據(jù)進程的行為周期性的調(diào)整進程的優(yōu)先級,較長時間未分配到CPU的進程優(yōu)先級通常增高,已經(jīng)在CPU上運行了較長時間的進程通常優(yōu)先級降低
用來配置優(yōu)先級的調(diào)用
-nice
-getpriority/setpriority
-sched_getscheduler/sched_setscheduler
-sched_getparam/sched_setparam
-sched_yield
-sched_get_priority_min/sched_get_priority_max
-sched_rr_get_interval
調(diào)度策略只是一種算法,內(nèi)核中的調(diào)度算法相關代碼使用了類似OOD中的策略模式
將調(diào)度算法與其他部分解耦合
理解整個系統(tǒng),在于理解進程調(diào)度的時機
schedule函數(shù)用于實現(xiàn)調(diào)度
-目的:在運行隊列中找到一個進程,把CPU分配給它
-調(diào)用方法:-直接調(diào)用schedule();-松散調(diào)用,根據(jù)need_resched標記
進程調(diào)度的時機
-中斷處理過程(包括時鐘中斷、I/O中斷、系統(tǒng)調(diào)用和異常)中,直接調(diào)用schedule(),或者返回用戶態(tài)時根據(jù)need_resched標記調(diào)用schedule();用戶態(tài)進程只能被動調(diào)度
-內(nèi)核線程可以直接調(diào)用schedule()進行進程切換,也可以在中斷處理過程中進行調(diào)度,也就是說內(nèi)核線程作為一類的特殊的進程可以主動調(diào)度,也可以被動調(diào)度;內(nèi)核線程是只有內(nèi)核態(tài)沒有用戶態(tài)的特殊進程;內(nèi)核現(xiàn)成可以主動調(diào)度可以被動調(diào)動
-用戶態(tài)進程無法實現(xiàn)主動調(diào)度,僅能通過陷入內(nèi)核態(tài)后的某個時機點進行調(diào)度,即在中斷處理過程中進行調(diào)度。
王瀟洋
原創(chuàng)作品轉(zhuǎn)載請注明出處《Linux內(nèi)核分析》MOOC課程[http://mooc.study.163.com/course/USTC-1000029000]