基于内核栈切换的进程切换
实验目的:将linux-0.11中采用的TSS切换部分去掉,取而代之的是基于堆栈的切换程序,写成一段基于堆栈切换的代码
要实现基于内核栈的任务切换,主要完成如下三件工作
- 重写switch_to
- 将重写的switch_to和schedule()函数接在一起
- 修改原本的fork()
第一步,修改schedule()函数
schedule函数在kernel/sched.c文件中
if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
c = (*p)->counter, next = i, pnext = *p;
//.......
switch_to(pnext, _LDT(next)); //修改switch_to,实验中的LDT缺少了一个下划线,这里要给它补上,不然会报错
//同时在schedule中要添加一个全局变量
struct task_struct *pnext = &(init_task.task);
在sched.c文件中,要定义一个全局变量tss,虽然我们放弃使用tss切换进程,但是在中断的时候,要找到内核栈的位置,并将用户态的SS:ESP以及EFLAGS这五个寄存器压到内核栈中,这是沟通用户栈和内核栈的桥梁,而找到用户栈位置就依靠TR指向的当前的TSS,所有进程都公用这个tss,即0号进程的tss。
struct tss_struct *tss = &(init_task.task.tss);
第二步,实现switch_to
实现switch_to主要在system_call.s文件中完成
重写TSS中的内核栈指针
ESP0 = 4
KERNEL_STACK = 12
state = 0 # these are offsets into the task-struct.
counter = 4
priority = 8
kernelstack = 12
signal = 16
sigaction = 20 # MUST be 16 (=len of sigaction)
blocked = (37*16)
在include/linux/sched.h</