賀邦+ 原創做品轉載請註明出處 + 《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 linux
1、理論知識git
Linux系統的通常執行過程github
最通常的狀況:正在運行的用戶態進程X切換到運行用戶態進程Y的過程算法
1. 正在運行的用戶態進程Xshell
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作了關鍵的進程上下文切換.net
5. 標號1以後開始運行用戶態進程Y(這裏Y曾經經過以上步驟被切換出去過所以能夠從標號1繼續執行)線程
6. restore_all //恢復現場調試
7. iret - pop cs:eip/ss:esp/eflags from kernel stack
8. 繼續運行用戶態進程Y
幾種特殊狀況
進程的調度時機與進程的切換
操做系統原理中介紹了大量進程調度算法,這些算法從實現的角度看僅僅是從運行隊列中選擇一個新進程,選擇的過程當中運用了不一樣的策略而已。
對於理解操做系統的工做機制,反而是進程的調度時機與進程的切換機制更爲關鍵。
進程調度的時機
進程的切換
31#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)
登錄實驗樓虛擬機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