李亚健 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
一、实验过程:
实验内容为完成一个简单的时间片轮转多道程序内核代码
1.根据老师指导按照实验步骤,在实验楼环境下打开shell:
cd LinuxKernel/linux-3.9.4
rm -rf mykernel
patch -p1 < ../mykernel_for_linux3.9.4sc.patch
make allnoconfig
make
qemu -kernel arch/x86/boot/bzImage
然后 cd mykernel
看到mymain.c和myinterrupt.c.
2.将老师github的mypcb.h/mymain.c/myinterrupt.c拷贝到实验楼环境的mykernel下,再按照实验步骤进行,即可看到实验的调度过程.修改这三个文件:
mypcb.h:
mymain.c:
myinterrupt.c:
3.重新make编译一下,然后执行会看到结果:
二、分析该精简内核的源代码。
1.mypcb.h对结构体和函数进行了定义.定义了线程的ip与sp 线程的结构,其中SP寄存器指向当前线程栈的栈顶,这样通过SP就能完成出入栈的操作;IP指向当前操作指令,一开始指向线程启动函数,后面按照代码的一层层调用,执行相应指令,接下来定义了进程控制块PCB的初始信息。
2.mymain.c中__init my_start_kernel 函数是内核的入口,它完成了初始化进程并启动进程的工作。 进程创建完毕后,将my_current_task指针指向0号进程,通过嵌入式汇编代码,开始执行。这个嵌入式代码实际上是开辟了新的栈帧空间,类似于上一课,也与myinterrupt.c的进程切换类似。 每个进程都执行my_process(void),i%10000000 == 0,打印进程号,略小于1s的时间。
3.myinterrupt.c中my_timer_handler被内核的定时器周期性调用,当计数到1000时执行进程切换。
4.其中的内嵌汇编代码为核心:
"pushl %%ebp\n\t" /* save ebp */
"movl %%esp,%0\n\t" /* save esp */
"movl %2,%%esp\n\t" /* restore esp */
"movl %2,%%ebp\n\t" /* restore ebp */
"movl $1f,%1\n\t" /* save eip */
"pushl %3\n\t"
"ret\n\t" /* restore eip */
: "=m" (prev->thread.sp),"=m" (prev->thread.ip)
: "m" (next->thread.sp),"m" (next->thread.ip)
"pushl %%ebp\n\t" /* save ebp */
"movl %%esp,%0\n\t" /* save esp */
"movl %2,%%esp\n\t" /* restore esp */
"movl %2,%%ebp\n\t" /* restore ebp */
"movl $1f,%1\n\t" /* save eip */
"pushl %3\n\t" "ret\n\t" /* restore eip */
: "=m" (prev->thread.sp),"=m" (prev->thread.ip)
: "m" (next->thread.sp),"m" (next->thread.ip)
三、理解操作系统是如何工作的。
1. Linux操作系统的正常工作可以说有三个非常重要的部分,就是我们的存储程序原理、堆栈以及中断的支持。 操作系统对进程的管理主要就是进程的管理和调度,我们为每个进程维护一个进程描述和以及进程间的关系。我们的内核的工作主要有两部分组成,首先运行有一个内核线程,然后就是一些中断处理程序的集合,我们在中断处理程序中要就行进程的调度。
2.Linux操作系统由内核来实现具体工作的,一个进程是通过系统调用fork()函数来创建的,先是将先前CPU正在运行的进程的进程上下文保存在内核态堆栈中,包括有eip,esp,ebp,cs等寄存器的数据;然后加载创建的进程的上下文信息到相应的寄存器中,运行当前新建进程;运行完毕后根据系统的调度继续执行相应的进程。Linux操作系统是多进程的操作系统,不同的进程就是基于以上的方式有操作系统实现调度运行的。同时,操作系统以一种中断的机制实现与用户的交互。操作系统中的IDT描述好各个中断对应的处理程序,当发生相对应的中断时,由硬件来实现中断信号的传递,CPU接收到相应的IRQ信号后,由操作系统如调度进程那样调度相应的处理程序,来完成相应的中断请求,实现与用户的交互。