網易云課堂《Linux內核分析》作業
實驗目的:
使用gdb跟蹤分析一個schedule()函數,理解Linux系統中進程調度的時機。
實驗過程:
登陸實驗樓虛擬機http://www.shiyanlou.com/courses/195
打開shell終端,執行以下命令:
cd LinuxKernel
rm -rf menu
git clone https://github.com/mengning/menu.git
cd menu
mv test_exec.c test.c
make rootfs
可以看到編譯出來的系統已經有了exec命令
可以通過增加-s -S啟動參數打開調試模式
qemu -kernel ../linux-3.18.6/arch/x86/boot/bzImage -initrd ../rootfs.img -s -S
打開gdb進行遠程調試
gdb
file ../linux-3.18.6/vmlinux
target remote:1234
設置斷點
b schedule
b context_switch
b switch_to
b pick_next_task
實驗分析:
通過實驗可知schedule()函數用來選擇一個新的進程來運行,并調用context_switch()進行上下文的切換,這個宏調用switch_to()來進行關鍵上下文切換,其中pick_next_task()函數封裝了進程調度算法。
實驗總結:
進程調度時機有三:
1、中斷處理過程(包括時鐘中斷、I/O中斷、系統調用和異常)中,直接調用schedule(),或者返回用戶態時根據need_resched標記調用schedule();
2、內核線程可以直接調用schedule()進行進程切換,也可以在中斷處理過程中進行調度,也就是說內核線程作為一類的特殊的進程可以主動調度,也可以被動調度;
3、用戶態進程無法實現主動調度,僅能通過陷入內核態后的某個時機點進行調度,即在中斷處理過程中進行調度。
進程切換:為了控制進程的執行,內核必須有能力掛起正在CPU上運行的進程,并恢復以前掛起的某個進程的執行。這種行為被稱為進程切換(process switch)、任務切換(task switch)或上下文切換(context switch)。
掛起正在CPU上執行的進程,與中斷時保存現場是不同的,中斷前后是在同一個進程上下文中,只是由用戶態轉向內核態執行。
進程上下文包含了進程執行需要的所有信息,包括:
1、用戶地址空間:?包括程序代碼,數據,用戶堆棧等
2、控制信息?:進程描述符,內核堆棧等
3、硬件上下文(與中斷保存硬件上下文的方法不同)
Linux系統的一般執行過程
最一般的情況:
正在運行的用戶態進程X切換到運行用戶態進程Y的過程
1、正在運行的用戶態進程X
2、發生中斷——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 //保存現場
4、中斷處理過程中或中斷返回前調用了schedule(),其中的switch_to做了關鍵的進程上下文切換
5、標號1之后開始運行用戶態進程Y(這里Y曾經通過以上步驟被切換出去過因此可以從標號1繼續執行)
6、restore_all //恢復現場
7、iret - pop cs:eip/ss:esp/eflags from kernel stack
8、繼續運行用戶態進程Y
幾種特殊情況:
1、通過中斷處理過程中的調度時機,用戶態進程與內核線程之間互相切換和內核線程之間互相切換,與最一般的情況非常類似,只是內核線程運行過程中發生中斷沒有進程用戶態和內核態的轉換;
2、內核線程主動調用schedule(),只有進程上下文的切換,沒有發生中斷上下文的切換,與最一般的情況略簡略;
3、創建子進程的系統調用在子進程中的執行起點及返回用戶態,如fork;
4、加載一個新的可執行程序后返回到用戶態的情況,如execve;
aapu原創作品轉載請注明出處《Linux內核分析》MOOC課