美文网首页
进程切换

进程切换

作者: const_qiu | 来源:发表于2020-09-22 22:02 被阅读0次

    进程控制块:

    struct proc_struct {
        enum proc_state state;                      // Process state
        int pid;                                    // Process ID
        int runs;                                   // the running times of Proces
        uintptr_t kstack;                           // Process kernel stack
        volatile bool need_resched;                 // bool value: need to be rescheduled to release CPU?
        struct proc_struct *parent;                 // the parent process
        struct mm_struct *mm;                       // Process's memory management field
        struct context context;                     // Switch here to run process
        struct trapframe *tf;                       // Trap frame for current interrupt
        uintptr_t cr3;                              // CR3 register: the base addr of Page Directroy Table(PDT)
        uint32_t flags;                             // Process flag
        char name[PROC_NAME_LEN + 1];               // Process name
        list_entry_t list_link;                     // Process link list 
        list_entry_t hash_link;                     // Process hash list
    };
    

    其中的context保存当前进程执行的上下文:

    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;
    };
    

    当前的进程current,即将要切换的进程next;

    .text
    .globl switch_to
    switch_to:                      # switch_to(from, to)
    
        # save from's registers;ESP
        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 函数的函数体,
    前半部分是保存当前的各种普通寄存器的值到进程的context 结构体中
    后半部分是把即将要切换到进程的context恢复到寄存器中,并修改了函数的返回地址;返回地址是forkret

    forkret(void) {
        forkrets(current->tf);
    }
    

    其中forkrets:

    forkrets:
        # set stack to this new process's trapframe
        movl 4(%esp), %esp
        jmp __trapret
    
    

    current 已经被修改成即将要执行的进程;

    kernel_thread(int (*fn)(void *), void *arg, uint32_t clone_flags) {
        struct trapframe tf;
        memset(&tf, 0, sizeof(struct trapframe));
        //设置中断帧,
        tf.tf_cs = KERNEL_CS;
        tf.tf_ds = tf.tf_es = tf.tf_ss = KERNEL_DS;
        tf.tf_regs.reg_ebx = (uint32_t)fn;
        tf.tf_regs.reg_edx = (uint32_t)arg;
        tf.tf_eip = (uint32_t)kernel_thread_entry;
        return do_fork(clone_flags | CLONE_VM, 0, &tf);
    }
    

    kernel_thread中已经设置好了trap_frame;以中断返回的形式切换执行流,开始执行eip指向的kernel_thread_entry,:

    .globl kernel_thread_entry
    kernel_thread_entry:        # void kernel_thread(void)
    
        pushl %edx              # push arg
        call *%ebx              # call fn ,ebx存放的是一个函数地址,函数参数存放在了edx 中,
    
        pushl %eax              # save the return value of fn(arg)
        call do_exit            # call do_exit to terminate current thread
    

    相关文章

      网友评论

          本文标题:进程切换

          本文链接:https://www.haomeiwen.com/subject/gqugyktx.html