標籤:
摘要: 潘俊洋 原創作品轉載請註明出處《Linux核心分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000
實驗目的:
使用gdb跟蹤分析一個schedule()函數,理解Linux系統中進程調度的時機。
實驗過程:
開啟shell終端,執行以下命令:
cd LinuxKernel
rm -rf menu
git clone https://github.com/mengning/menu.git
cd menu
mv test_exec.c test.c
make rootfs
可以通過增加-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;
理解進程調度時機跟蹤分析進程調度與進程切換的過程