switch_to 理解
最近看linux0.11源码时,看到任务切换函数switch_to,感觉很晦涩,于是在网上查了一些资料,现在终于有些眉目,特记录于此,以方便大家参考,有什么错误或不足之处,还请大家指出~
switch_to源码
/*
* switch_to(n) should switch tasks to task nr n, first
* checking that n isn't the current task, in which case it does nothing.
* This also clears the TS-flag if the task we switched to has used
* tha math co-processor latest.
*/
#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])); \
}
大部分代码都很容易看懂,主要是:判断当前任务是否是要切换的任务,是则跳到标号1,即不做任何事;交换;调整等。。。
这里重点强调_TSS(n) 和ljmp %0;
(2)_TSS(n),作用是生成TSS的段选择符
#define FIRST_TSS_ENTRY 4
#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
当通过以上两个代码是不足以明白_TSS(n)的机制,需要结合以下知识;
上图描述linux内核中GDT的布局;0-nul, 1-cs, 2-ds, 3-syscall, 4-TSS0, 5-LDT0, 6-TSS1 等。。。
上图是段选择符,TI=0表示在GDT(全局描述符表)中,1表示在LDT(局部描述符表)中,RPL表示优先级;描述符索引就是在GDT中的索引;
通过上面两张图,下面分析代码,从图1可以看出第一个TSS位于索引为4的位置,于是#define FIRST_TSS_ENTRY 4;而FIRST_TSS_ENTRY<<3表示左移3位,因为TI和RPL总共占3为;((unsigned long) n)<<4为什么要左移4位呢?从图1可以看出TSS索引都是偶数,于是TI(1位)+RPL(2位)+偶数位(1)=4;通过上述组合就可以得到TSS选择子;
()ljmp %0或(ljmp *%0)
首先是为什么要加*?这是gas语法,表示绝对跳转(与C中的*是不同的),若程序没有加*,则编译器会自己加上*,可以在linux中测试;
ljmp用法说明:(很重要)
按AS手册,ljmp指令存在两种形式,即:
一、直接操作数跳转,此时操作数即为目标逻辑地址(选择子,偏移),即形如:ljmp $seg_selector, $offset的方式;
二、使用内存操作数,这时候,AS手册规定,内存操作数必须用“*”作前缀,即形如:ljmp *mem48,其中内存位置mem48处存放目标逻辑地址: 高16bit存放的是seg_selector,低32bit存放的是offset。注意:这条指令里的“*”只是表示间接跳转的意思,与C语言里的“*”作用完全不同。
回到源码上,ljmp %0用的ljmp的第二种用法,“ljmp *%0”这条语句展开后相当于“ljmp *__tmp.a”,也就是跳转到地址&__tmp.a中包含的48bit逻辑地址处。而按struct _tmp的定义,这也就意味着__tmp.a即为该逻辑地址的offset部分,__tmp.b的低16bit为seg_selector(高16bit无用)部分。由于在"ljmp %0"之前,"movw %%dx,%1"这条语句已经把状态段选择子"__TSS(n)"的值赋给了__tmp.b的低16bit。至于为什么要用*&__tmp.a,目前还不清楚,其实*&__tmp.a和__tmp.a是一样的,通过汇编也可以看出;这里就先不用关心它了;
通过以上说明,可以知道了ljmp将跳转到选择子指定的地方,大致过程是,ljmp判断选择子为TSS类型,于是就告诉硬件要切换任务,硬件首先它要将当前的PC,esp,eax等现场信息保存在当前自己的TSS段描述符中,然后再将目标TSS段描述符中的pc,esp,eax的值拷贝至对应的寄存器中.当这些过程全部做完以后内核就实现了内核的切换;可以参考下图:
总结:
通过以上内容,可以大致了解到任务切换的流程,switch_to中关键是ljmp %0;
switch_to 理解的更多相关文章
- LINUX内核分析期末总结
韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.课程总结 1 ...
- Linux内核分析之理解进程调度时机跟踪分析进程调度与进程切换的过程
一.原理分析 1.调度时机 背景不同类型的进程有不同的调度需求第一种分类I/O-bond:频繁的进行I/O:通常会花费很多时间等待I/O操作的完成CPU-bound:计算密集型:需要大量的CPU时间进 ...
- 20135202闫佳歆--week 8 实验:理解进程调度时机跟踪分析进程调度与进程切换的过程--实验及总结
week 8 实验:理解进程调度时机跟踪分析进程调度与进程切换的过程 1.环境搭建: rm menu -rf git clone https://github.com/megnning/menu.gi ...
- 对于Linux内核执行过程的理解(基于fork、execve、schedule等函数)
382 + 原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/ 一.实验环境 win10 -> VMware -> Ubuntu1 ...
- Linux内核分析--理解进程调度时机、跟踪分析进程调度和进程切换的过程
ID:fuchen1994 姓名:江军 作业要求: 理解Linux系统中进程调度的时机,可以在内核代码中搜索schedule()函数,看都是哪里调用了schedule(),判断我们课程内容中的总结是否 ...
- Linux内核设计第八周学习总结 理解进程调度时机跟踪分析进程调度与进程切换的过程
陈巧然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.视频内容 Linux ...
- 理解进程调度时机跟踪分析进程调度与进程切换的过程(Linux)
----------------------------------------------------------------------------------- 理解进程调度时机跟踪分析进程调度 ...
- linux 内核的 switch_to原理
switch_to:这是一个宏,有三个参数prev,next,last 局部变量prev,next:指向进程描述符的内存地址 首先明确的是:last和prev是同一个,用last只是为了理解方便,完全 ...
- 《深入理解Linux内核》 读书笔记
深入理解Linux内核 读书笔记 一.概论 操作系统基本概念 多用户系统 允许多个用户登录系统,不同用户之间的有私有的空间 用户和组 每个用于属于一个组,组的权限和其他人的权限,和拥有者的权限不一样. ...
随机推荐
- MYSQL序言
我写MYSQL的文章主要的原因:我发现网上关于MYSQL的文章比较少,而且很多都是参差不齐,几乎找不到可以比较全面的介绍:例如一篇文章介绍如何增删改查,却没有介绍批量新增:于是下次工作中用到的时候又要 ...
- [javascript|基本概念]学习笔记
1/语法 a.区分大小写 b.标识符(首字符必须是字母/"_"/"$",其他可为字母/"_"/"$"/数字,不能用关键字 ...
- android ListView_显示数据库数据
xml <?xml version="1.0"?> -<LinearLayout tools:context=".MainActivity" ...
- FTP协议及工作原理详解
1. FTP协议 什么是FTP呢?FTP 是 TCP/IP 协议组中的协议之一,是英文File Transfer Protocol的缩写. 该协议是Internet文件传送的基础,它由一系列规格说明文 ...
- 不同浏览器的DNS超时重发机制(一)
一.Chrome浏览器(37.0.2062.124 m) 1.在Win7环境下,DNS超时重发的时间间隔为:2s.2s.2s.2s(在这个时刻重复发2个DNS请求).2s.4s,再经过大约14s左右, ...
- C#定时器和事件
C#定时器和事件 System.Timers.Timer myTimer; private void Form1_Load(object sender, EventArgs e) { myTimer ...
- JAVA多线程学习--生产者消费者问题
一.问题描述 生产者消费者问题是一个典型的线程同步问题.生产者生产商品放到容器中,容器有一定的容量(只能顺序放,先放后拿),消费者消费商品,当容器满了后,生产者等待,当容器为空时,消费者等待.当生产者 ...
- string和stringBuilder的区别
曾经被问到过这个问题,回答得不是很好,在网上找了一下,园子里有大神很详细地讨论了二者的区别. http://www.cnblogs.com/yunfeng8967/articles/1093832.h ...
- [转]一个基于完成端口的TCP Server Framework,浅析IOCP
[转]一个基于完成端口的TCP Server Framework,浅析IOCP http://www.cppblog.com/adapterofcoms/archive/2010/06/26/1187 ...
- Window.Open参数、返回值
一.window.open()支持环境: JavaScript1.0+/JScript1.0+/Nav2+/IE3+/Opera3+ 二.基本语法: window.open(pageURL,name, ...