日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

理解进程调度时机跟踪分析进程调度与进程切换的过程

發(fā)布時(shí)間:2023/12/18 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 理解进程调度时机跟踪分析进程调度与进程切换的过程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

虞嘯川 + 原創(chuàng)作品轉(zhuǎn)載請注明出處 + 《Linux內(nèi)核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000

?

Linux既支持普通的分時(shí)進(jìn)程,也支持實(shí)時(shí)進(jìn)程,即基于優(yōu)先級。Linux中調(diào)度是多種調(diào)度策略和調(diào)度算法的混合,因?yàn)椴煌愋偷倪M(jìn)程有不同的調(diào)度需求,所以其調(diào)度時(shí)機(jī)也是不同的。這些算法讓系統(tǒng)運(yùn)行的更高效,讓CPU資源得到最大限度使用。而所謂的策略就是一組規(guī)則,決定了什么時(shí)候以怎樣的方式選擇一個(gè)新的進(jìn)程運(yùn)行。 操作系統(tǒng)原理中介紹了大量進(jìn)程調(diào)度算法,這些算法從實(shí)現(xiàn)的角度看僅僅是從運(yùn)行隊(duì)列中選擇一個(gè)新進(jìn)程,選擇的過程中運(yùn)用了不同的策略而已。對于理解操作系統(tǒng)的工作機(jī)制,反而是進(jìn)程的調(diào)度時(shí)機(jī)與進(jìn)程的切換機(jī)制更為關(guān)鍵。

?在linux中進(jìn)程的調(diào)度依賴schedule()函數(shù),下面我們通過gdb跟蹤一下這個(gè)函數(shù)。

使用gdb跟蹤分析一個(gè)schedule()函數(shù)??

設(shè)置斷點(diǎn)

schedule

schedule調(diào)用了__schedule

在__schedule中調(diào)用了pick_next_task選擇一個(gè)新的進(jìn)程來運(yùn)行,然后調(diào)用context_switch進(jìn)行上下文切換

context_switch

進(jìn)程調(diào)度時(shí)機(jī)

  • 中斷處理過程(包括時(shí)鐘中斷、I/O中斷、系統(tǒng)調(diào)用和異常)中,直接調(diào)用schedule(),或者返回用戶態(tài)時(shí)根據(jù)need_resched標(biāo)記調(diào)用schedule();

  • 內(nèi)核線程可以直接調(diào)用schedule()進(jìn)行進(jìn)程切換,也可以在中斷處理過程中進(jìn)行調(diào)度,也就是說內(nèi)核線程作為一類的特殊的進(jìn)程可以主動(dòng)調(diào)度,也可以被動(dòng)調(diào)度;

  • 用戶態(tài)進(jìn)程無法實(shí)現(xiàn)主動(dòng)調(diào)度,僅能通過陷入內(nèi)核態(tài)后的某個(gè)時(shí)機(jī)點(diǎn)進(jìn)行調(diào)度,即在中斷處理過程中進(jìn)行調(diào)度。

switch_to

#define switch_to(prev, next, last) \ 32do { \ 33 /* \ 34 * Context-switching clobbers all registers, so we clobber \ 35 * them explicitly, via unused output variables. \ 36 * (EAX and EBP is not listed because EBP is saved/restored \ 37 * explicitly for wchan access and EAX is the return value of \ 38 * __switch_to()) \ 39 */ \ 40 unsigned long ebx, ecx, edx, esi, edi; \ 41 \ 42 asm volatile("pushfl\n\t" /* save flags */ \ 43 "pushl %%ebp\n\t" /* save EBP */ \ 44 "movl %%esp,%[prev_sp]\n\t" /* save ESP */ \ 45 "movl %[next_sp],%%esp\n\t" /* restore ESP */ \ 46 "movl $1f,%[prev_ip]\n\t" /* save EIP */ \ 47 "pushl %[next_ip]\n\t" /* restore EIP */ \ 48 __switch_canary \ 49 "jmp __switch_to\n" /* regparm call */ \ 50 "1:\t" \ 51 "popl %%ebp\n\t" /* restore EBP */ \ 52 "popfl\n" /* restore flags */ \ 53 \ 54 /* output parameters */ \ 55 : [prev_sp] "=m" (prev->thread.sp), \ 56 [prev_ip] "=m" (prev->thread.ip), \ 57 "=a" (last), \ 58 \ 59 /* clobbered output registers: */ \ 60 "=b" (ebx), "=c" (ecx), "=d" (edx), \ 61 "=S" (esi), "=D" (edi) \ 62 \ 63 __switch_canary_oparam \ 64 \ 65 /* input parameters: */ \ 66 : [next_sp] "m" (next->thread.sp), \ 67 [next_ip] "m" (next->thread.ip), \ 68 \ 69 /* regparm parameters for __switch_to(): */ \ 70 [prev] "a" (prev), \ 71 [next] "d" (next) \ 72 \ 73 __switch_canary_iparam \ 74 \ 75 : /* reloaded segment registers */ \ 76 "memory"); \ 77} while (0)

?在context_switch中調(diào)用了switch_to(prev, next, prev);完成了上下文保存和切換的工作,prev和next分別指向當(dāng)前進(jìn)程和下一個(gè)要切換的進(jìn)程。

42 43當(dāng)前進(jìn)程的flags和ebp壓棧;44當(dāng)前esp保存至內(nèi)存;45 存入下一個(gè)進(jìn)程的esp,至此已切換至下一個(gè)進(jìn)程的堆棧;46 47把當(dāng)前進(jìn)程的$1f標(biāo)號保存至當(dāng)前ip,并將下一進(jìn)程的ip壓棧;48 49執(zhí)行完該函數(shù)iret將下一進(jìn)程的ip出棧,至此切換至下一個(gè)進(jìn)程;最后將ebp和flags出棧,正式執(zhí)行下一進(jìn)程

switch_to對應(yīng)的堆棧

asm volatile("pushfl\n\t" /* save flags */ \ 43 "pushl %%ebp\n\t" /* save EBP */ \ 44 "movl %%esp,%[prev_sp]\n\t" /* save ESP */ \ 45 "movl %[next_sp],%%esp\n\t" /* restore ESP */ \ 46 "movl $1f,%[prev_ip]\n\t" /* save EIP */ \ 47 "pushl %[next_ip]\n\t" /* restore EIP */ \ "movl %[next_sp],%%esp\n\t" /* restore ESP */
"movl $1f,%[prev_ip]\n\t" /* save EIP */這兩句將堆棧的sp作了保存和切換
然后將下一個(gè)進(jìn)程的ip壓棧

48 __switch_canary \ 49 "jmp __switch_to\n" /* regparm call */ \ 50 "1:\t" \ 51 "popl %%ebp\n\t" /* restore EBP */ \ 52 "popfl\n" /* restore flags */ \

next_stack變成了prev_stack,next_ip出棧,切換至下一個(gè)進(jìn)程,然后pop ebp? popfl開始執(zhí)行下一個(gè)進(jìn)程的代碼

$1f是同一個(gè)地址,然而卻有著不同的上下文環(huán)境。

總結(jié)

一、當(dāng)x用戶態(tài)進(jìn)程通過進(jìn)程調(diào)度策略切換到用戶態(tài)進(jìn)程y時(shí),

最一般的情況:正在運(yùn)行的用戶態(tài)進(jìn)程X切換到運(yùn)行用戶態(tài)進(jìn)程Y的過程

1.正在運(yùn)行的用戶態(tài)進(jìn)程X

2.發(fā)生中斷——save cs:eip/esp/eflags(current) to kernel stack,then load cs:eip(entry of a specific ISR) and ss:esp(point to kernel stack).

3.SAVE_ALL //保存現(xiàn)場

4.中斷處理過程中或中斷返回前調(diào)用了schedule(),其中的switch_to做了關(guān)鍵的進(jìn)程上下文切換

5.標(biāo)號1之后開始運(yùn)行用戶態(tài)進(jìn)程Y(這里Y曾經(jīng)通過以上步驟被切換出去過因此可以從標(biāo)號1繼續(xù)執(zhí)行)

6.restore_all //恢復(fù)現(xiàn)場

7.iret - pop cs:eip/ss:esp/eflags from kernel stack

8.繼續(xù)運(yùn)行用戶態(tài)進(jìn)程Y

幾種特殊情況

1.通過中斷處理過程中的調(diào)度時(shí)機(jī),用戶態(tài)進(jìn)程與內(nèi)核線程之間互相切換和內(nèi)核線程之間互相切換,與最一般的情況非常類似,只是內(nèi)核線程運(yùn)行過程中發(fā)生中斷沒有進(jìn)程用戶態(tài)和內(nèi)核態(tài)的轉(zhuǎn)換;

2.內(nèi)核線程主動(dòng)調(diào)用schedule(),只有進(jìn)程上下文的切換,沒有發(fā)生中斷上下文的切換,與最一般的情況略簡略;

3.創(chuàng)建子進(jìn)程的系統(tǒng)調(diào)用在子進(jìn)程中的執(zhí)行起點(diǎn)及返回用戶態(tài),如fork;

4.加載一個(gè)新的可執(zhí)行程序后返回到用戶態(tài)的情況,如execve;

?

二、有關(guān)進(jìn)程切換

1.為了控制進(jìn)程的執(zhí)行,內(nèi)核必須有能力掛起正在CPU上執(zhí)行的進(jìn)程,并恢復(fù)以前掛起的某個(gè)進(jìn)程的執(zhí)行,這叫做進(jìn)程切換、任務(wù)切換、上下文切換;

2.掛起正在CPU上執(zhí)行的進(jìn)程,與中斷時(shí)保存現(xiàn)場是不同的,中斷前后是在同一個(gè)進(jìn)程上下文中,只是由用戶態(tài)轉(zhuǎn)向內(nèi)核態(tài)執(zhí)行;

3.進(jìn)程上下文包含了進(jìn)程執(zhí)行需要的所有信息

(1)用戶地址空間: 包括程序代碼,數(shù)據(jù),用戶堆棧等

(2)控制信息 :進(jìn)程描述符,內(nèi)核堆棧等

(3)硬件上下文(注意中斷也要保存硬件上下文只是保存的方法不同)

4.schedule()函數(shù)選擇一個(gè)新的進(jìn)程來運(yùn)行,并調(diào)用context_switch進(jìn)行上下文的切換,這個(gè)宏調(diào)用switch_to來進(jìn)行關(guān)鍵上下文切換

(1)next = pick_next_task(rq, prev);//進(jìn)程調(diào)度算法都封裝這個(gè)函數(shù)內(nèi)部

(2)context_switch(rq, prev, next);//進(jìn)程上下文切換

(3)switch_to利用了prev和next兩個(gè)參數(shù):prev指向當(dāng)前進(jìn)程,next指向被調(diào)度的進(jìn)程

?

內(nèi)核是各種中斷處理過程和內(nèi)核線程的集合,3g以上部分是所有進(jìn)程共享的

轉(zhuǎn)載于:https://www.cnblogs.com/yuxiaochuan/p/5402770.html

總結(jié)

以上是生活随笔為你收集整理的理解进程调度时机跟踪分析进程调度与进程切换的过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。