20135202闫佳歆--week 8 实验:理解进程调度时机跟踪分析进程调度与进程切换的过程--实验及总结...
week 8 實驗:理解進程調度時機跟蹤分析進程調度與進程切換的過程
1.環(huán)境搭建:
rm menu -rf git clone https://github.com/megnning/menu.git cd menu ls make rootfs qemu -kernel ../linux-3.18.6/arch/x86/boot/bzImage -initrd ../rootfs.img -s -S gdb file ../linux-3.18.6/vmlinux target remote:1234這一堆都是常用配置了,不贅述。
2.使用gdb跟蹤分析一個schedule()函數(shù)
首先設置幾個斷點,分別是schedule, pick_next_task,context_switch,switch_to。最后一個switch_to設置失敗了,我也無法定位到它,這個另外再說。
 設置斷點如下:
發(fā)現(xiàn)一個對schdule的調用:
schdule函數(shù)定義如下:
 __visible保證任何地方都能夠調用這個函數(shù)實現(xiàn)進程的切換。
 它首先要建立一個進程描述符,用來表示當前進程,而具體的調度過程交由__schedule()函數(shù)執(zhí)行。
由這張圖可以看出來,兩個重要的函數(shù)context_switch和pick_next_task函數(shù)都在__schedule函數(shù)中。
首先看到的是pick_next_task函數(shù):
 next指針指向的是由這個函數(shù)選擇出來的進程,pick_next_task函數(shù)里面封裝了許多進程調度的算法,通過這個函數(shù)就能尋找出適當?shù)南乱粋€執(zhí)行進程。內部如下:
然后看到了context_switch函數(shù),這個函數(shù)的功能是進程上下文切換
關于switch_to:
 switch_to是關鍵上下文切換的相關代碼,切換堆棧和寄存器的狀態(tài),利用了prev和next兩個參數(shù):prev指向當前進程,next指向被調度的進程。
 這段是匯編相關無法跟蹤,我只找到了一個__switch_to的函數(shù),這個函數(shù)的返回值應該是eax的值。
對于switch_to的代碼分析如下:
31 #define switch_to(prev, next, last) 32 do { 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" /* 保存當前進程的標志位 */ 43 "pushl %%ebp\n\t" /* 保存當前進程的堆棧基址EBP */ 44 "movl %%esp,%[prev_sp]\n\t" /* 保存當前棧頂ESP */ 45 "movl %[next_sp],%%esp\n\t" /* 把下一個進程的棧頂放到esp寄存器中,完成了內核堆棧的切換,從此往下壓棧都是在next進程的內核堆棧中。 */ 46 "movl $1f,%[prev_ip]\n\t" /* 保存當前進程的EIP */ 47 "pushl %[next_ip]\n\t" /* 把下一個進程的起點EIP壓入堆棧 */ 48 __switch_canary 49 "jmp __switch_to\n" /* 因為是函數(shù)所以是jmp,通過寄存器傳遞參數(shù),寄存器是prev-a,next-d,當函數(shù)執(zhí)行結束ret時因為沒有壓棧當前eip,所以需要使用之前壓棧的eip,就是pop出next_ip。 */ 以上四行代碼實際是使用next進程的進程堆棧,但是還算成prev的進程執(zhí)行,內核堆棧的切換和進程切換完成并不同時間。50 "1:\t" /* 認為next進程開始執(zhí)行。 */ 51 "popl %%ebp\n\t" /* restore EBP */ 52 "popfl\n" /* restore flags */ 53 54 /* output parameters 因為處于中斷上下文,在內核中prev_sp是內核堆棧棧頂prev_ip是當前進程的eip */ 55 : [prev_sp] "=m" (prev->thread.sp), 56 [prev_ip] "=m" (prev->thread.ip), //[prev_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: next_sp下一個進程的內核堆棧的棧頂next_ip下一個進程執(zhí)行的起點,一般是$1f,對于新創(chuàng)建的子進程是ret_from_fork*/ 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)簡而言之,原理如下:
schedule()函數(shù)選擇一個新的進程來運行:
使用pick_next_task內部封裝的調度算法執(zhí)行選擇
 并調用context_switch進行上下文的切換
 context_switch又調用switch_to來進行關鍵上下文切換
 switch_to切換堆棧和寄存器的狀態(tài),利用了prev和next兩個參數(shù):
 prev指向當前進程,next指向被調度的進程。
3.學習筆記
請走鏈接 學習筆記
轉載于:https://www.cnblogs.com/20135202yjx/p/5392618.html
總結
以上是生活随笔為你收集整理的20135202闫佳歆--week 8 实验:理解进程调度时机跟踪分析进程调度与进程切换的过程--实验及总结...的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: MyEclipse Servers视窗出
- 下一篇: 12.UiAutomator 获取系统信
