zoukankan      html  css  js  c++  java
  • linux模式切换,进程切换

    内核态和用户态的切换:

    用户态到内核态的转换:1、进行系统调用,2、异步中断,3、外部硬件中断

    检查特权级别的变化:当异常发生在用户态,而异常处理函数则必须运行在内核态,则此时必须调用内核态的堆栈(系统调用必然是发生特权级的变化),步骤是,将进程的TSS段中的esp0和ss0赋值给esp,ss寄存器

    于是乎,当进程由用户态进入内核态时,必发生中断,因为内核态的CPL优先级高,所以要进行栈的切换。那么就会读tr寄存器以访问该进程(现在还是用户态)的TSS段。随后用TSS中内核态堆栈段ss0和栈指针esp0装载SS和esp寄存器,这样就实现了用户栈到内核栈的切换了。同时,内核用一组mov指令保存所有寄存器到内核态堆栈上,这也包括用户态中ss和esp这对寄存器的内容。

    最后将先前由中断向量检索得到的中断处理程序的cs,eip信息装入相应的寄存器,开始执行中断处理程序,这时就转到了内核态的程序执行了。

    进程切换:

    这里再次强调一下,每个进程都有一个thread_struct结构的字段thread,用于保留进程的一部分硬件上下文:

    这里再次强调一下,每个进程都有一个thread_struct结构的字段thread,用于保留进程的一部分硬件上下文:
    struct thread_struct {
        struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
        unsigned long   esp0;
        unsigned long   sysenter_cs;
        unsigned long   eip;
        unsigned long   esp;
        unsigned long   fs;
        unsigned long   gs;
        unsigned long   debugreg[8]; 
        unsigned long   cr2, trap_no, error_code;
        union i387_union    i387;
        struct vm86_struct __user * vm86_info;
        unsigned long       screen_bitmap;
        unsigned long       v86flags, v86mask, saved_esp0;
        unsigned int        saved_fs, saved_gs;
        unsigned long   *io_bitmap_ptr;
        unsigned long   io_bitmap_max;
    };

    待会我们就将看到,其实里边最有用的就是eip和esp两个字段,分别表示保存的指令和堆栈栈顶的偏移地址。但这里不包括ss寄存器的值,因为所有的切换都在内核态,那么只用为内核态的堆栈基址ss0保存一次就行了,你们这些进程切来切去,我都不便应万变,把它保存在每个CPU所对应的那个TSS段中。这里也得出了一个很重要的结论,为了提高效率,所有内核态的进程堆栈段基地址都是相同的。

    thread字段存放的都是内核栈的esp和eip,然后_switch_to()宏,此时已经进入要切换进来进程的内核栈中,把已经切换进来的进程的thread.esp0装入本地cpu的esp0字段

    切换前:被切换进程的内核栈,压入ebp,eflag,然后把被切换进程内核栈的esp赋值给本进程的thread.esp。

    切换进来的进程,把本进程的thread.ESP赋值给esp,此时便切换到本进程中,但是局部变量没有完成切换,(向prev->thread.eip存入标记为1的地址。当被替换的进程重新恢复执行时,进程执行我们下面标记为1的那条指令:)这里的prev变量依旧属于被切换的进程。

    5. 宏把next->thread.eip的值(绝大多数情况下是上面所述标记为1的地址)压入next的内核栈:
        pushl next->thread.eip

    注意体会,当next执行完了以后的函数后,会回到这个栈的位置,执行eip对应的那条指令。

    6.    跳到__switch_to()函数:
       jmp  __switch_to

    7. 如干程序执行后,当A将再次获得CPU时,它执行一些保存eflags和ebp寄存器内容内容的指令,这两条指令的第一条指令被标记为1:
       1:
            popl %ebp
            popfl

  • 相关阅读:
    JAVA_集合_作业01
    Java_Objects_hashCode
    Java成员内部类
    Java集合练习_实现购物车需求
    Java初级_单例设计模式
    HelloWorld
    vue中视频标点
    防抖节流?俩者区别?vue如何使用防抖、节流来解决点击问题?
    keep-alive
    axios和ajax的区别
  • 原文地址:https://www.cnblogs.com/kkshaq/p/4547911.html
Copyright © 2011-2022 走看看