- 论坛徽章:
- 0
|
原帖由 sherf 于 2008-10-30 23:48 发表
yhb04,
对于你回复的最后一点,即
2)从上面2来看,进程切换似乎只解决了如何获得 esp0 的值,而没有提到进程如何获得 esp3 (这里 esp3 指的是用户堆栈指针)。我想如果要切换至用户进程,肯定也要一起切换 ...
那如果是这样的话,在进程调度模块调度进程B的时候,我想顺序应该是:M(RING0)-> B(RING0),B(RING0)->B(RING3),那如果进程表里面保存的是esp3,那esp0从何而来?
或许我的问题描述的未必很清楚,那我想我先说说我目前的理解(这是后来我在上一贴里面补充的):
假设以下场景:
M:进程调度模块(CPL=0)
A:用户进程1(CPL=3)
B:用户进程2(CPL=3)
C:用户进程3(CPL=0)
如果 A->B,则必须经过以下过程:
1)A(ring 3) -> A(ring 0)
2)A(ring 0) -> M(ring 0)
3)M(ring 0) -> B(ring 0)
4)B(ring 0) -> B(ring 3)
上面的转换有问题,内核(包括进程调度模块M)是进程的仆从(内核是进程的仆从,但是它有比用户进程大的多的权利,很像天朝的人民公仆),所以M是以进程A或B的名义在运行,所以A(Ring0)=M(Ring0)
所以
1)A(Ring3)->A(Ring0)
2)A(Ring0)->B(Ring0)
3)B(Ring0)->B(Ring3)
其中,
对于1),就是常说的 ring 3-> ring 0,而且从这可以判断出 "ring 3->ring 0"必定是对同一进程而言(比如说1)里面指的就是用户进程A,ring0和ring3则只是指A的两种运行状态)。就像如果存在A->C,虽然看上去也是从特权级3->特权级0,但这个不是指我们常说的"ring 3-> ring 0"。而堆栈的切换是从 “进程A的用户栈”切换至“进程A的内核栈”。esp0的获取:esp0<-TSS.esp0<-进程表中的esp域。
对于2),属于进程调度模块对进程A的操作。会发生堆栈切换吗?还是说堆栈操作仅仅对A的内核栈的操作而言。
对于3),属于进程调度模块对进程B的操作。会发生堆栈切换吗?还是说堆栈操作仅仅对B的内核栈的操作而言。
对于4),与1)类似,就是常说的 ring 0-> ring 3 。而堆栈的切换是从“进程B的内核栈”切换至“进程B的用户栈”。esp3的获取:未知?
你的2)不存在,M一直在用A的内核栈
你的3)实际行是A(Ring0)->B(Ring0),就是在这个阶段进行内核堆栈切换。
你的4)从B的内核态返回用户态,用户态堆栈信息在B的内核栈中,由 iret指令自动完成切换。
在这4点中,只有1)用到TSS,而且 esp0 的值指的是”用户进程A“在 ring0 状态下(即内核栈)的堆栈入口指针。
没错。 |
|