linux cpu 特权级之间的翻转,操作系统篇之-特权级切换过程和进程切换过程

4 Linux的做法:

1)Linux没有为每一个进程都准备一个tss段,而是每一个cpu使用一个tss段,tr寄存器保存该段。进程切换时,只更新唯一tss段中的esp0字段到新进程的内核栈。

2)Linux的tss段中只使用esp0和iomap等字段,不用它来保存寄存器,在一个用户进程被中断进入ring0的时候,tss中取出esp0,然后切到esp0,其它的寄存器则保存在esp0指示的内核栈上而不保存在tss中。

3)结果,Linux中每一个cpu只有一个tss段,tr寄存器永远指向它。符合x86处理器的使用规范,但不遵循intel的建议,这样的后果是开销更小了,因为不必切换tr寄存器了。

5 进程切换过程总结

进程A正在RING3正常运行(ss0_A在初始化tss的时候赋值了,esp0在启动进程A的时候,设置为了进程表中进程A的s_stackframe的最高地址),这时时钟中断(用于进程切换)发生,根据1、2的介绍,CPU的硬件自动将CPU的ss,

esp指向TSS里面的ss0,

esp0,由前面我们知道,esp0是A进程的s_stackframe的最高地址,所以CPU的esp指向了A进程表的s_stackframe中的最高地址,CPU自动把进程A的ss1_A,esp1_A以及eflags1_A,

cs1_A,

eip1_A五个寄存器值压栈,这5个寄存器的值就被压入到A进程表的s_stackframe结构里面,这个结构最高地址开始的5项正好是储存ss,esp,eflags,cs,eip的。然后CPU就将控制权交给了中断处理程序或者进程调度程序。终端处理程序中,首先把esp0_A的值加4,然后继续压eax1_A,

ecx1_A, edx1_A, ebx1_A, esp1_A, esi1_A, edi1_A, ds1_A, es1_A,

fs1_A,

gs1_A这些寄存器的值,由于esp0_A还在A进程表s_stackframe中,所以这些寄存器被依次压入到了A进程表的s_stackframe中保存起来(进程表s_stackframe的结构就是按照这个顺序来安排的)。

进程调度程序然后将进程B的进程表s_stackframe结构的最低地址(对应着gs1_B)赋给esp0,然后通过和保存A进程寄存器相反的过程,弹出进程B进程表中保存的进程B的寄存器,从gs1_B一直到eax1_B,然后将esp+4(上边的弹出过程已经使esp指向了retaddr,所以为了配合下面的iretd指令,需要esp+4,指向eip1_B),最后通过iretd命令返回到进程B(ring1)(IRETD指令弹出堆栈中数据送EIP,CS,EFLAGS,ESP,

SS)。返回后,内核中的esp0由于堆栈内容全部弹出,指向了进程B的s_stackframe的最高地址,当进程B被切换进入到内核时,重复上面A的过程

看到这里,你可能会想,在内核中,esp必须指向进程表,才能够保证优先级切换,进程切换时得到正确的结果,但是如果我们要调用复杂的进程调度程序,比如进程调度程序不止一个函数,这时一定会用到堆栈操作,那么我们的进程表立刻被破坏掉。所以我们需要切换堆栈,将esp指向另外的位置。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值