操作系统任务调度
内存分页
当前我们内存使用分页, 一个page有4k。长度0x1000。
以0x1000开始的这个page为例子。
这个区域作为栈来使用,由于栈是方向增长,所以,栈顶为0x2000, 0x1000为栈底。
进程控制块PCB
在栈底0x1000的位置存放一个进程控制块,目前进程控制块存放的内容很简单
pub struct Task {
pub stack: *mut TaskFrame, // 任务栈信息
}
PCB里就存放了进程切换的时候的任务栈信息,其实就是进城切换时的esp寄存器的值。
进程切换的实现
首先定一个数据结构,这个数据结构里能保存恢复一个进程执行的基本信息。目前就这么多了。
pub struct TaskFrame {
pub edi: usize,
pub esi: usize,
pub ebx: usize,
pub ebp: usize,
pub eip: usize,
}
主要来看看核心的部分,进程切换,此处我使用汇编实现。
task_switch:
push ebp
mov ebp, esp
push ebx
push esi
push edi
mov eax, esp
and eax, 0xFFFFF000 ; Task变量的地址
mov [eax], esp ; 保存当前任务栈信息
mov eax, [ebp + 8] ; 读next参数
mov esp, [eax] ; 切换任务栈
pop edi
pop esi
pop ebx
pop ebp
ret
在调用task_switch函数的时候,call指令本身就会在栈中压入调用后位置eip的值,其实也就是等会切换回这个进程的时候要返回的位置的地址。
call task_switch