8.11和Linux相似的任务切换方法

8.11和Linux相似的任务切换方法

有些人认为TSS切换任务太慢了,因为TSS切换的过程中硬件要做太多操作了

详细可以看Intel手册硬件完成了哪些操作

所以我们手动保存这些寄存器信息

我们采用的就是将其保存在任务自己的栈中

一个函数调用另一个函数,有些寄存器是可以不用保存的,有些要自己保存

详细要看Intel手册abi386-4第37页

EIP当前代码的位置,就是那个返回地址

esp栈顶指针,esp要指向栈顶,所以无法通过栈来保存此时的栈顶指针,所以保存在task_t结构体里面

typedef struct _task_t {
	uint32_t * stack;
	tss_t tss;				// 任务的TSS段
	uint16_t tss_sel;		// tss选择子
}task_t;

因为涉及栈的操作,所以需要汇编代码来写

//task.c
void simple_switch (uint32_t ** from, uint32_t * to);

void task_switch_from_to (task_t * from, task_t * to) {
    // switch_to_tss(to->tss_sel);
    simple_switch(&from->stack, to->stack);
}
//D:\code\x86\code\start\start\source\kernel\init\start.S
// simple_switch(&from,&to)
	.text
	.global simple_switch
simple_switch: //有个问题就是不用保存void task_switch_from_to (task_t * from, task_t * to)的返回IP吗?所以我感觉下面两个要多移4个字节
	movl 4(%esp), %eax   // esp往栈底移动4个字节(一个单位),然后取出其内容,然后取from->stack
	movl 8(%esp), %edx   // esp往栈底移动8个字节(两个单位),然后取出其内容,取to->stack

	// 保存前一任务(也可以说为本任务)状态
	push %ebp
	push %ebx
	push %esi
	push %edi

	// 切换栈
	mov %esp, (%eax)    // 将from->stack = esp
  	mov %edx, %esp      // esp = to->stack

	// 加载下一任务的栈(但是一开始init_task_entry(void)函数的栈是空的,所以需要我们手动给栈赋初值)
	pop %edi
	pop %esi
	pop %ebx
	pop %ebp
	
  	ret
//D:\code\x86\code\start\start\source\kernel\core\task.c
int task_init (task_t *task, uint32_t entry, uint32_t esp) { //init_task_entry(void)的esp为一个初始化的数组
    ASSERT(task != (task_t *)0);

    // tss_init(task, entry, esp);
    uint32_t * pesp = (uint32_t *)esp;
    if (pesp) {
        *(--pesp) = entry; //任务函数的入口地址(相当于EIP)在栈底,给ret用
        *(--pesp) = 0;
        *(--pesp) = 0;
        *(--pesp) = 0;
        *(--pesp) = 0;
        task->stack = pesp; //这是init_task_entry(void)函数的esp
    }
    return 0;
}

测试:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值