本次作业仍然分为两部分,第一部分为实验。
如实验楼的实验过程所述:使用实验楼的虚拟机打开shell,然后cd mykernel 您可以看到qemu窗口输出的内容的代码mymain.c和myinterrupt.c。
代码如下:
cd LinuxKernel/linux-3.9.4
qemu -kernel arch/x86/boot/bzImage
实验截图如下:
通过观察我们会发现my_start_kernel和my_timer_handler快速的交替执行。
接下来查看mymain.c和myinterrupt.c代码。
首先我们分析mymain.c,包含两个函数两个函数, my_start_kernel和my_process。
首先是my_start_kernel:
初始化0号进程,将esp指向task[0]的堆栈stack顶端。 将task[0].thread.sp即堆栈顶端地址压栈,为以后的%ebp的复位使用。 将task[0].thread.ip即程序入my_process压栈。通过ret指令,将task[0].thread.ip即程序入口my_process放到eip。之后的pop %ebp是下一个被调度到的process第一个执行的代码。
my_process函数:
my_process中每10000000个循环输出信息,并且调用my_schedule函数。
接下来我们分析myinterrupt.c文件:
myinterrupt.c同样包含my_timer_handler和my_schedule两个函数。
my_timer_handler每隔1000次将my_need_sched置1,调用进程的调度函数。 my_schedule保存恢复进程上下文。
总结:
通过本次实验,更加深刻了解了操作系统时间片轮转的基本原理,即先初始化若干进程,并执行第一个进程,当CPU分配给进程的时间片用完时,便需要进行进程切换:先保存进程的上下文,即进程栈的栈顶esp和ebp,并通过将eip压栈和弹栈的方式进行切换。
那么linux是如何进行进程管理的,接下来就是本次作业的第二部分内容,看书第三章和第五章进行深入学习。
通过学习,我将linux执行进程的过程总结如下:
1.通过task_struct进程描述符来描述进程,也就是表示进程。
2.通过fork()创建进程,这也是上课老师主要强调的为何演示代码执行以后好像返回了两次,实际上fork()会重新创建一个进程。
3.通过exec()将执行映像装入地址空间。
4.进程的消亡,调用exit()。
接着我们来看看什么叫系统调用,系统调用把应用程序的请求传给内核,调用相应的的内核函数完成所需的处理,将处理结果返回给应用程序。