“操作系统实验”实验报告

基于内核栈切换的进程切换

实验名称:基于内核栈切换的进程切换

实验日期:2021.6.3

班级:物联网193

姓名:伏星

学号:1930110717

一、实验目的

深入理解进程和进程切换的概念; 综合应用进程、CPU 管理、PCB、LDT、内核栈、内核态等知识解决实际问题; 开始建立系统认识。

二、实验环境

Linux

三、实验内容

编写汇编程序 switch_to: 完成主体框架; 在主体框架下依次完成 PCB 切换、内核栈切换、LDT 切换等; 修改 fork(),由于是基于内核栈的切换,所以进程需要创建出能完成内核栈切换的样子。 修改 PCB,即 task_struct 结构,增加相应的内容域,同时处理由于修改了 task_struct 所造成的影响。 用修改后的 Linux 0.11 仍然可以启动、可以正常使用。 (选做)分析实验 3 的日志体会修改前后系统运行的差别。

问题1:针对下面的代码片段: movl tss,%ecx addl $4096,%ebx movl %ebx,ESP0(%ecx) copy 回答问题: (1)为什么要加 4096; (2)为什么没有设置 tss 中的 ss0

(1)因为进程的PCB和Linux 0.11进程的内核栈在一个内存上,栈位于页内存的高地址,PCB位于页内存的低地址,最开始指向页内存的最顶端。

(2)因为tss.ss0是一个内核数据段,而只需要用到一个tss,所以不需要设置tss中的ss0了。

针对代码片段: *(--krnstack) = ebp; *(--krnstack) = ecx; *(--krnstack) = ebx; *(--krnstack) = 0; copy 回答问题:

(1)子进程第一次执行时,eax=?为什么要等于这个数?哪里的工作让 eax 等于这样一个数? (2)这段代码中的 ebx 和 ecx 来自哪里,是什么含义,为什么要通过这些代码将其写到子进程的内核栈中? (3)这段代码中的 ebp 来自哪里,是什么含义,为什么要做这样的设置?可以不设置吗?为什么?

答:(1)子进程第一次执行时,eax=0,因为要和父进程分开运行copy_process(),成功初始化进程copy_process后赋值eax得到。

(2)这段代码中的ebx和ecx来自copy_process()的形参,含义是指一段寄存器。是由fork函数决定,作用是让父子的内核栈在初始化时完全一致。

(3)这段代码中的ebp来自用户栈地址,不需要设置否则子进程就没有用户栈。

问题 3:为什么要在切换完 LDT 之后要重新设置 fs=0x17?而且为什么重设操作要出现在切换完 LDT 之后,出现在 LDT 之前又会怎么样?

答:因为通过fs访问进程的用户态内存,LDT切换完成即切换了分配给进程的用户态内存地址空间,因此前一个fs指向的是上一个进程的用户态内存,如果想要执行下一个进程的用户态内存,就需要用这两条指令来重取fs。 出现在LDT之前访问的是上一个进程的用户态内存。

四、实验过程及数据记录

将 Linux 0.11 中的 switch_to (在 kernal/system_call.s 中)实现去掉,写成一段基于堆栈切换的代码。 图片描述

schedule() 函数(在 kernal/sched.c 中)做稍许修改 图片描述

修改sched.h文件 图片描述

在sched.h中修改PCB的task_struct

图片描述 修改#define INIT_TASK 图片描述 修改fork.c 图片描述 文件修改后进行编译: 图片描述 运行 图片描述

五、实验结果分析

如截图所示都运行成功

六、实验心得

本次实验很有难度,经过不断尝试最后成功完成实验,课后还需要加强巩固。

最新评论
暂无评论~