ucore内核态进程上下文切换关键代码分析

目录

进程切换关键代码

上下文切换函数定义

上下文切换函数调用

进程上下文切换整体流程

proc_run执行流程

jmp switch_to如何改变了指令控制流程

执行jmp switch_to指令时,栈情况

进程上下文切换三个过程

第一阶段,跳转到switch_to函数入口

第二阶段,保存from上下文

第三阶段,恢复to上下文


内核态进程切换关键代码

上下文切换函数定义

void switch_to(struct context *from, struct context *to);
.text
.globl switch_to
switch_to:                      # switch_to(from, to)

    # save from's registers
    movl 4(%esp), %eax          # eax points to from
    popl 0(%eax)                # save eip !popl
    movl %esp, 4(%eax)          # save esp::context of from
    movl %ebx, 8(%eax)          # save ebx::context of from
    movl %ecx, 12(%eax)         # save ecx::context of from
    movl %edx, 16(%eax)         # save edx::context of from
    movl %esi, 20(%eax)         # save esi::context of from
    movl %edi, 24(%eax)         # save edi::context of from
    movl %ebp, 28(%eax)         # save ebp::context of from

    # restore to's registers
    movl 4(%esp), %eax          # not 8(%esp): popped return address already
                                # eax now points to to
    movl 28(%eax), %ebp         # restore ebp::context of to
    movl 24(%eax), %edi         # restore edi::context of to
    movl 20(%eax), %esi         # restore esi::context of to
    movl 16(%eax), %edx         # restore edx::context of to
    movl 12(%eax), %ecx         # restore ecx::context of to
    movl 8(%eax), %ebx          # restore ebx::context of to
    movl 4(%eax), %esp          # restore esp::context of to

    pushl 0(%eax)               # push eip

    ret

上下文切换函数调用

struct context {
    uint32_t eip;
    uint32_t esp;
    uint32_t ebx;
    uint32_t ecx;
    uint32_t edx;
    uint32_t esi;
    uint32_t edi;
    uint32_t ebp;
};
void proc_run(struct proc_struct *proc) 
{
	L1: local_intr_save(intr_flag);
	L2: switch_to(&(prev->context), &(next->context));
	L3: local_intr_restore(intr_flag);
}

内核态进程上下文切换整体流程

proc_run执行流程

void proc_run(struct proc_struct *proc) 
{
	L1: local_intr_save(intr_flag);
	L2: switch_to(&(prev->context), &(next->context));
	L3: local_intr_restore(intr_flag);
}

ucore内核态进程上下文切换关键代码分析_第1张图片

jmp switch_to如何改变了指令控制流程

CPU执行指令只靠CS:IP两个寄存器,这条指令的执行最终改变了什么呢?其实关键点在于jmp指令改变了当前的IP值,用个图解释这个原因。等待下次执行指令的时候,CPU通过IP寄存器获得当前执行的指令movl 4(%esp), %eax,这就完成了指令跳转。

ucore内核态进程上下文切换关键代码分析_第2张图片

执行jmp switch_to指令时,栈情况

ucore内核态进程上下文切换关键代码分析_第3张图片

内核态进程上下文切换三个过程

在第2节中,分析了proc_run函数执行的整体流程,在这里将进一步分析switch_to汇编代码。

void switch_to(struct context *from, struct context *to);
.text
.globl switch_to
switch_to:                      # switch_to(from, to)

    # save from's registers
    movl 4(%esp), %eax          # eax points to from
    popl 0(%eax)                # save eip !popl
    movl %esp, 4(%eax)
    movl %ebx, 8(%eax)
    movl %ecx, 12(%eax)
    movl %edx, 16(%eax)
    movl %esi, 20(%eax)
    movl %edi, 24(%eax)
    movl %ebp, 28(%eax)

    # restore to's registers
    movl 4(%esp), %eax          # not 8(%esp): popped return address already
                                # eax now points to to
    movl 28(%eax), %ebp
    movl 24(%eax), %edi
    movl 20(%eax), %esi
    movl 16(%eax), %edx
    movl 12(%eax), %ecx
    movl 8(%eax), %ebx
    movl 4(%eax), %esp

    pushl 0(%eax)               # push eip

    ret

第一阶段,跳转到switch_to函数入口

ucore内核态进程上下文切换关键代码分析_第4张图片

第二阶段,保存from上下文

核心,切换到from的context中,并将当前的EIP保存到from.context.eip中,这样完成进程控制流的保存。

ucore内核态进程上下文切换关键代码分析_第5张图片

第三阶段,恢复to上下文

核心,切换至to的context中,将to.context.eip放入栈的函数返回值中,这样切换到另外一个进程控制流。

ucore内核态进程上下文切换关键代码分析_第6张图片

你可能感兴趣的:(操作系统,操作系统)