实验名称:基于内核栈切换的进程切换
实验日期:5月24日
班级:软嵌191
姓名:游金明
学号:1930110795
一、实验目的
三、实验内容
四、实验过程及数据记录
$ tar -zxvf hit-oslab-linux-20110823.tar.gz
-C /home/shiyanlou/
切换目录
$ cd /home/shiyanlou/oslab/
确认路径 $ pwd
查看目录内容 $ ls -l
2.修改sched.c
if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
c = (*p)->counter, next = i;
//......
switch_to(next);
copy
修改为
if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
c = (*p)->counter, next = i, pnext = *p;
//.......
switch_to(pnext, LDT(next));
copy
3.删除sched.h中switch_to
4.在system_call.s重写switch_to
重写first_return_kernel
first_return_kernel:
popl %edx
popl %edi
popl %esi
pop %gs
pop %fs
pop %es
pop %ds
iret
copy
设置全局可见
.globl switch_to
.globl first_return_from_kernel
copy
5.修改fork()系统调用
6.forck.c修改
-注释基于tss进程切换机制时的代码,
p->tss.back_link = 0;
p->tss.esp0 = PAGE_SIZE + (long) p;
p->tss.ss0 = 0x10;
copy
krnstack指针指向子进程的内核栈
long * krnstack = (long *)(PAGE_SIZE+(long)p);
copy
初始化内核栈(krnstack)中的内容:
*(--krnstack) = ss & 0xffff;
*(--krnstack) = esp;
*(--krnstack) = eflags;
*(--krnstack) = cs & 0xffff;
*(--krnstack) = eip;
*(--krnstack) = (long) first_return_kernel;//处理switch_to返回的位置
*(--krnstack) = ebp;
*(--krnstack) = ecx;
*(--krnstack) = ebx;
*(--krnstack) = 0;
copy
添加extern声明
extern long switch_to;
extern long first_return_from_kernel;
copy
五、实验结果分析
-编译
-测试
switch_to (在 kernal/system_call.s 中)实现去掉,写成一段基于堆栈切换的代码。
六、实验心得
-问题1
(1)这里的ebx寄存器指向的是下一个进程的PCB,加上4096后,即为一个进程分配4KB(4*1024)的空间,栈顶即为内核栈的指针,栈底即为进程的PCB。
(2)因为进程的切换不依靠tss,但CPU的机制造成对每个进程仍然会有TR寄存器、tss的设置等内容,所以可以让所有的进程都共用tss0的空间,所以不需要设置tss0。
-问题2
(1)这里eax等于0,即返回值,这里设置就可以用if(!fork())来判断是不是子进程,最后一行(--krnstack) = 0完成了这件事。
(2)ebx和ecx都来自copy_process()函数传进来的参数,存放的是父进程的ebx和ecx,通过将父进程的参数压入栈中,就可以保证子进程回到用户态的时候具有和父进程相同的环境。
(3)ebp也是来自copy_process()函数传进来的参数,只是存放的是父进程的用户栈指针。即在fork()刚刚执行完copy_process()的时候,它的用户栈是父进程的用户栈,而非自己的用户栈,当子进程执行其他操作的时候,造成需要的栈将要与父进程不同了,才会创建自己的用户栈,这么做的好处是当一些子进程什么都不做时系统不用分配额外的空间,当然也可以创建子进程就为它分配一个新的栈,esp指向新的栈顶。
-问题3
首先要知道FS的作用: 操作系统就是通过FS在内核态中找到用户程序的地址的,切换LDT的时候,也就是会切换进程使用的用户栈,所以用户地址已经改变了,自然FS也要跟着改变,如果出现在切换LDT之前就可能会影响其他进程查找对应的用户地址。
本次实践项目就是将 Linux 0.11 中采用的 TSS 切换部分去掉,取而代之的是基于堆栈的切换程序。具体的说,就是将 Linux 0.11 中的 switch_to 实现去掉,写成一段基于堆栈切换的代码。
学习时间 280分钟
操作时间 96分钟
按键次数 556次
实验次数 9次
报告字数 3756字
是否完成 完成