贺邦+ 原创做品转载请注明出处 + 《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