Linux内核分析:实验二

刘畅 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

写在前面

本实验是模拟Linux内核的工作过程,包括进程上下文的切换和基于时间片轮转的进程调度。在实验平台的基础上,简要的完成一个简单的多道程序内核代码。

进程的描述

在这个实验中,在mypcb.h中,用结构体PCB描述进程的特性,比如进程id、进程的栈、进程内的线程等,这个结构体是一个链表形式组织的。其中进程中的线程用Thread结构体描述,包含栈顶地址和指令指针的地址。如下图所示:

这里写图片描述

进程的初始化

进程的初始化:在mymain.h中对进程进行了初始化,即把进程的pid、进程中线程的栈顶指针初始化以及组织成一个进程链表形式,并且把每个进程的入口地址都指向my_process函数。如下图所示:

这里写图片描述

0号进程:首先执行的是pid为0的进程,然后通过内嵌汇编的形式交给CPU执行,它将当前进程的栈顶地址放到esp寄存器中,然后将要调度进程的栈帧和进程的ip保存到栈中,通过弹栈ret的方式,将eip指向要调度进程的入口地址(my_process函数)。如下图所示:

这里写图片描述

my_process函数:这个函数不停的加1,直到加到结果为10000000的时候,将调度状态改为0,打印当前进程的信息,并通过my_schedule函数实现进程的调度。

进程的调度

my_schedule函数在myinterrupt.c中实现的,它找到进程链表中的下一个进程,进行调度。

如果即将调度的进程从未运行过,那么需要为新进程构造一个堆栈,即把esp和ebp的寄存器的值,全都置为新进程的sp所指的地方。如下图所示:

这里写图片描述

如果即将调度的进程之前运行过,那么它的栈底指针ebp的值保存在栈中了,就不需要对其赋值了。

进程切换时,需要将正在运行的进程的栈底指针ebp保存在栈中,将栈顶指针esp和当前指针指针寄存器eip的值保存在PCB结构体中。然后把下个进程的esp和eip放到对应的寄存器中。如下图所示:

这里写图片描述

运行结果

这里写图片描述

实验总结

这个代码虽然简陋,但其体现了Linux内核中进程启动和切换的过程。

进程的启动

使用内嵌汇编的形式,为待运行的进程开辟栈空间,并让CPU的eip寄存器指向进程的入口点。

进程的切换

先保存进程的上下文,即栈顶指针esp的值和eip寄存器的值,这些信息是存放在PCB中的,而栈底指针ebp的值是放到栈中的。

并依据进程调度算法,选出下一个要调度的进程,判断待调度的进程之前是否运行过。若运行过就需要通过弹栈的方式找到它的栈帧ebp,若没运行过,直接将PCB中记录的sp的值放到ebp中。然后将待调度进程的运行点(入口点)放到eip中,这是通过先把ip值压到栈中,再ret的形式实现的。因为我们是无法直接修改eip值的。

ret 指令相当于 pop eip

刘畅 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值