实验介绍
作者学号238.
原创作品转载请注明出处 https://github.com/mengning/linuxkernel/
实验准备
打开VMware虚拟机,运行ubuntu18,执行如下命令:
sudo apt-get install qemu # install QEMU
sudo ln -s /usr/bin/qemu-system-i386 /usr/bin/qemu
wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.9.4.tar.xz # download Linux Kernel 3.9.4 source code
wget https://raw.github.com/mengning/mykernel/master/mykernel_for_linux3.9.4sc.patch # download mykernel_for_linux3.9.4sc.patch
xz -d linux-3.9.4.tar.xz
tar -xvf linux-3.9.4.tar
cd linux-3.9.4
patch -p1 < …/mykernel_for_linux3.9.4sc.patch
make allnoconfig
make
qemu -kernel arch/x86/boot/bzImage 从qemu窗口中您可以看到my_start_kernel在执行,同时my_timer_handler时钟中断处理程序周期性执行。
如图,mymain和myinterrupt展示了mykernel在启动之后,系统调用my_start_kernel函数,并周期性调用my_timer_handler函数。
实验过程
make clean
make allnoconfig
make
qemu -kernel arch/x86/boot/bzImage
代码解释
pcb.h
mypcb.h对进程的PCB进行了数据结构的定义,一些常量的定义,还有my_schedule函数的声明。
宏:
MAX_TASK_NUM 代表最大进程数为10
KERNEL_STACK_SIZE 代表每个进程堆栈的大小
PRIORITY_MAX 代表了进程们的优先级从0到30
PCB中,
pid 进程的唯一标识,用于区分进程
state 进程当前的状态,之所以声明为volatile是希望编译器不要对其进行优化,保证每次都能从内存中获取此值。
stack[KERNEL_STACK_SIZE] 进程的堆栈
thread 进程的ip(程序指针)和sp(栈顶指针)
task_entry 进程的入口
next下一个PCB,将所有PCB连起来,形成环,从而不断循环切换进程。
mymain.c
通过首先运行函数__init my_start_kernel,初始化首个进程pid为0,之后通过for循环初始化其他进程,连接pcb。
myinterrupt.c
my_timer_handler被内核的定时器周期性调用,当计数到2000时执行进程切换
总结
- Linux操作系统的正常工作可以说有三个非常重要的部分,就是我们的存储程序原理、堆栈以及中断的支持。 操作系统对进程的管理主要就是进程的管理和调度,我们为每个进程维护一个进程描述和以及进程间的关系。我们的内核的工作主要有两部分组成,首先运行有一个内核线程,然后就是一些中断处理程序的集合,我们在中断处理程序中要就行进程的调度。
- Linux操作系统由内核来实现具体工作的,一个进程是通过系统调用fork()函数来创建的,先是将先前CPU正在运行的进程的进程上下文保存在内核态堆栈中,包括有eip,esp,ebp,cs等寄存器的数据;然后加载创建的进程的上下文信息到相应的寄存器中,运行当前新建进程;运行完毕后根据系统的调度继续执行相应的进程。Linux操作系统是多进程的操作系统,不同的进程就是基于以上的方式有操作系统实现调度运行的。同时,操作系统以一种中断的机制实现与用户的交互。操作系统中的IDT描述好各个中断对应的处理程序,当发生相对应的中断时,由硬件来实现中断信号的传递,CPU接收到相应的IRQ信号后,由操作系统如调度进程那样调度相应的处理程序,来完成相应的中断请求,实现与用户的交互。