switch_to(n)函数
来源:互联网 发布:微信接口开发教程 java 编辑:程序博客网 时间:2024/05/17 02:31
这篇文章我们来分析switch_to()函数, 分析的代码取自linux kernel 0.11 sched.h文件, 我们只为说明原理, 所以尽量简单. 其中代码注释参考了赵炯老师<Linux内核完全注释>一书, 言归正传,下面来看switch_to()函数.
switch_to(n)将切换当前任务到任务n.首先检测任务n是不是当前任务,是则直接退出.
输入: %0 – 指向_tmp 1% - 指向_tmp.b处, 用于存放新TSS的选择符
dx – 新任务n的TSS段选择符 ecx – 新任务n的任务结构指针task[n].
_tmp用于jump指令的操作数, 其中a值是32位偏移地址, 而b的低2字节是新TSS段的选择符. 细心的读者看到a并没有被赋值,可以思考一下这是为什么
#define switch_to(n) {\struct {long a,b;} __tmp; \__asm__("cmpl %%ecx,_current\n\t" \"je 1f\n\t" \"movw %%dx,%1\n\t" \"xchgl %%ecx,_current\n\t" \"ljmp %0\n\t" \"cmpl %%ecx,_last_task_used_math\n\t" \"jne 1f\n\t" \"clts\n" \"1:" \::"m" (*&__tmp.a),"m" (*&__tmp.b), \"d" (_TSS(n)),"c" ((long) task[n])); \}
3. 检查任务n是当前任务吗?
4. 是则什么都不做,退出
5. 将新任务TSS的16位选择子存入_tmp.b中.
6. 当前任务变为task[n]; ecx = 被切换出的任务.
7. 长跳转到*&_tmp, 造成任务切换. 我们可以看之前的一篇文章<JMP指令>, 其中代码34行, 指明了任务切换时要调用的函数TaskSwitch(), 下面我们将分析这个函数具体要做什么.
8. 原任务使用过协处理器吗
9. 没有,则跳转退出.
10. 原任务使用过协处理器, 清cr0中的任务切换标志TS
下面介绍<JMP指令>一文中伪代码函数TaskSwitch()做了哪些事情
TaskSwitch(SelectorType Selector, SegAttributes Attributes, int Base, int Limit, int Linkage){SelectorType OldTSS;if(Limit < 103)SegmentException($TS, Selector);AccessTSSState(1); //WriteTR.Base = Base;TR.Limit = Limit;TR.Attributes = Attributes;OldTSS = TR.Selector; TR.Selector = Selector;AccessTSSState(0); //readif(Linkage == 1){AccessLinear(TR.Base, 2, 0, 1, &OldTSS); EFLAGS.NT = 1;SetTSSBusy(Selector, 1);}else if(Linkage == -1)SetTSSBusy(OldTSS, 0);else if(Linkage == 0){SetTSSBusy(OldTSS, 0);SetTSSBusy(Selector, 1);}CR0.TS = 1;CPL = CS.Selector.RPL;LDTR.Attributes.Present = 0;CS.Attributes.Present = 0;SS.Attributes.Present = 0;CS.Attributes.Present = 0;DS.Attributes.Present = 0;ES.Attributes.Present = 0;FS.Attributes.Present = 0;GS.Attributes.Present = 0;if(LDTR.Selector.TI == 1)SegmentException($TS, LDTR.Selector);if((LDTR.Selector & 0FFFCh) == 0)LDTR.Attributes.P = 0;else{ReadDescriptor(LDTR.Selector, &Attributes, &Base, &Limit, &GSelector, &GOffset);if((Attributes.DType == 1)|| (Attributes.Type != 2)|| (Attributes.Present == 0))SegmentException($TS, LDTR.Selector);SetAccessed(LDTR.Selector);LDTR.Attributes = Attributes;LDTR.Base = Base;LDTR.Limit = Limit;}JumpGate(CS.Selector, EIP, $TS);SRegLoad(SS, SS.Selector, $TS);SRegLoad(DS, SS.Selector, $TS);SRegLoad(ES, SS.Selector, $TS);SRegLoad(FS, SS.Selector, $TS);SRegLoad(GS, SS.Selector, $TS);}4. 任务状态段至少有104个字节
6. 当前机器的状态(EIP, EFLAGS,EAX,ECX, EDX, ESP, EBP…….)保存到老任务的TSS中
7-11 TR及投影寄存器指向新任务的TSS, 原来任务的selector保存到OldTSS中
12. 把新任务TSS中的内容装入到硬件寄存器(EIP,EFLAGS, EAX,ECX, EDX, ESP, EBP…….)中.
13-25 根据链家字段的值做不同的处理
26-27 设置任务切换位及当前特权级
28-35 各描述符投影寄存器存在位预置为0
36-37 LDTR的选择子必须指定全局描述符表,否则产生异常
38-39 局部描述符表可以为空, 如为空, 将描述符表存在位设置为0
40. 局部描述符表非空
41-51 读出描述符的属性, 基地址和段界限. 检查出错,产生段异常. 之后装入局部描述符表投影寄存器.
52. 装入CS投影寄存器
53-57 装入SS, DS, ES, FS, GS投影寄存器
下面给出JumpGate的伪代码, 经过<JMP一文>,相信读者可以自行分析.
JumpGate(SelectorType Selector, int Offset, int GP){ SegAttributes Attributes; SelectorType GSelector; int Base, Limit, GOffset; if((Selector&0FFFCh) == 0) SegmentException(GP, 0); ReadDescriptor(Selector,&Attributes,&Base,&Limit,&GSelector,&GOffset); if(Attributes.DType == 0) SegmentException(GP, Selector); Selector.RPL = 0; CSDescriptorLoad(Selector,Attributes,Base,Limit,GP); if(Offset > CS.Limit) SegmentException(GP, 0); CS.Selector = Selector; CS.Selector.RPL = CPL; EIP = Offset;}
- switch_to(n)函数
- linux内核switch_to函数
- switch_to
- switch_to
- switch_to
- Linux进程(之)进程切换函数switch_to()解析
- switch_to 宏
- linux下的schedule()函数详解,以及进程的调度,current_thread_info,switch_to宏等笔记
- Linux switch_to()深入分析
- Linux switch_to()深入分析
- 进程切换switch_to()注释
- Linux kernel-<armv7a-switch_to>
- selenium switch_to.frame
- linux0.11中switch_to理解
- 分析进程切换宏 switch_to
- linux0.11中switch_to理解
- Linux 0.12 switch_to切换过程
- linux0.11任务切换switch_to
- MYSQL模糊查询
- Javascript刷新页面的几种方法(页面刷新与弹出窗口问题解决方法)
- windows phone 7中文本缩略显示方法
- Google Protocol Buffer 的使用和原理
- 凸包graham扫描法
- switch_to(n)函数
- 计算机网络试卷4
- 十三周任务四 Csolid CBox CBall CCylinder
- 面向对象的C语言框架尝鲜
- 字典树 poj 2001
- 查看Linux系统位数命令
- TCP/IP数据传输过程
- win7 下cmd运行sqlplus报错以下错误。SP2-1503: 无法初始化Oracle 调用界面,SP2-1503: 无法初始化Oracle 调SP2-0152
- 错误expected unqualified-id before string constant