xv6中存储cpu和进程信息的技巧
xv6是一个支持多处理器的Unix-like操作系统,
近日阅读源码时发现xv6在记录当前CPU和进程状态时非常tricky
首先,上代码:
extern struct cpu cpus[NCPU]; extern int ncpu; // Per-CPU variables, holding pointers to the // current cpu and to the current process. // The asm suffix tells gcc to use "%gs:0" to refer to cpu // and "%gs:4" to refer to proc. seginit sets up the // %gs segment register so that %gs refers to the memory // holding those two variables in the local cpu's struct cpu. // This is similar to how thread-local variables are implemented // in thread libraries such as Linux pthreads. extern struct cpu *cpu asm("%gs:0"); // &cpus[cpunum()] extern struct proc *proc asm("%gs:4"); // cpus[cpunum()].proc
其中struct cpu是一个用来保存每个cpu运行状态的结构体,
代码第一行定义了结构体数组cpus[NCPU],NCPU对应cpu的总数(最大为8),也就是说cpus用来存储所有cpu的运行状态。
那么问题来了:上面的内核代码是运行于每个cpu之中的,那每个cpu如何知道自身的当前运行状态呢?
对于这个问题,我们可以通过lapic获取cpu自身编号,再利用编号对cpus寻址即可,
也就是说,对于任意一个cpu,自身状态的存储位置可以这样获得: struct cpu *c = &cpus[cpunum()];
然而,第二个问题来了:我们不可能每次引用cpu自身状态时都通过lapic获取编号啊,能不能弄一个全局变量把状态位置一次性存储下来呢?
像是这样, struct cpu *cpu; //全局变量,存储cpu自身状态 ,然后在初始化代码中 cpu = c ;
对于记录每个cpu正在运行的进程也有这样的问题,能不能写成: struct proc *proc; //全局变量,存储当前cpu正在运行的进程状态
那么,第三个问题来了:每个cpu是独立并行的,在每个cpu上运行的内核代码都是一样的,页表也一样,
这意味着全局变量cpu和proc的地址也是一样的,这样便不可以用来区分不同cpu的状态了。
因此,我们需要一种方法,可以让我们在每个cpu中都用同一个符号记录状态,但这些符号却是映射到不同的地址。
既然页表一样,我们自然不能用一个绝对的数值来寻址啦,仔细想想,页表之上有什么?页表之上,还有段表啊。
所以我们需要用segment register来寻址,只要我们在建立段表时把该段都映射到不同的内存区域不就可以了,所以我们有了以下声明:
extern struct cpu *cpu asm("%gs:0"); // &cpus[cpunum()] extern struct proc *proc asm("%gs:4"); // cpus[cpunum()].proc
我们用gs作为段寄存器,cpu指向[%gs],proc指向[%gs+4],
其中为什么开头要用extern呢?我问过某大神,他说是因为gs段是在外部建立的,相当于外部定义的。。。
OK,最后一个问题来了,gs段应该指向哪,才能确保每个cpu的gs段都位于不同的区域?
最直观的想法当然是指向对应的cpus[num]内部啦,所以在struct cpu尾部增加两个域:
struct cpu{ ........ //cpu状态 // Cpu-local storage variables; see below struct cpu *cpu; struct proc *proc; // The currently-running process. }
然后在建立段表时,增加gs段,并映射至尾部这两个域:
c = &cpus[cpunum()]; ......... //建立其他段 // 建立gs段,共两个域(存储cpu和proc地址),起始地址为&c->cpu c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, , ); //加载gdt lgdt(c->gdt, sizeof(c->gdt)); //加载gs loadgs(SEG_KCPU << ); // 把当前cpu和proc状态的地址赋给cpu和proc全局变量 //而cpu变量实质为%gs:0, proc变量实质为%gs:4 cpu = c; proc = ;
其实在这里cpu和proc变量跟线程局部存储的性质差不多,每个处理器都可以引用同一个变量,但这些变量都对应不同的存储区域。
有可能这种实现技巧跟TLS(线程局部存储)差不多,有空研究下TLS的实现看看是不是。
xv6中存储cpu和进程信息的技巧的更多相关文章
- 从零自学Java-3.在程序中存储和修改变量信息
1.创建变量: 2.使用不同类型的变量: 3.在变量中存储值: 4.在数学表达式中使用变量: 5.把一个变量的值赋给另一个变量: 6.递增/递减变量的值. 程序Variable:使用不同类型的变量并赋 ...
- MySQL 调优基础(一) CPU与进程
一般而言,MySQL 的调优可以分为两个层面,一个是在MySQL层面上进行的调优,比如SQL改写,索引的添加,MySQL各种参数的配置:另一个层面是从操作系统的层面和硬件的层面来进行调优.操作系统的层 ...
- linux中使用top获取进程的资源占用信息
在linux中使用top获取进程的资源占用信息: Cpu(s): 1.0%us, 0.0%sy, 0.0%ni, 98.3%id, 0.7%wa, 0.0%hi, 0.0%si, 0.0 ...
- 【Linux】 linux中的进程信息相关的一些内容
_ linux进程信息 ■ top top命令用于动态地查看系统的进程和其他一些资源的信息.开启top的时候可以加上-t <sec>来设置top更新的频率高低.进入top界面之后,可以输入 ...
- Android中获取系统内存信息以及进程信息-----ActivityManager的使用(一)
本节内容主要是讲解ActivityManager的使用,通过ActivityManager我们可以获得系统里正在运行的activities,包括 进程(Process)等.应用程序/包.服务(Serv ...
- 在Linux中通过Top运行进程查找最高内存和CPU使用率
按内存使用情况查找前15个进程,在批处理模式下为"top" 使用top命令查看有关当前状态,系统使用情况的更详细信息:正常运行时间,负载平均值和进程总数. 分类:Linux命令操作 ...
- C#获取CPU占用率、内存占用、磁盘占用、进程信息
代码: using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading ...
- JAVA 在程序中存储和修改信息
1.语句和表达式 计算机程序是一组告诉计算机什么的指令,每一个指令称为语句. 2.指定变量类型 变量名.变量存储的信息类型 整型int(-2.14*109~2.14*109).浮点型float(38位 ...
- Linux中查看CPU信息【转】
[转自]:http://blog.chinaunix.net/uid-23622436-id-3311579.html cat /proc/cpuinfo中的信息 processor 逻辑 ...
随机推荐
- 转:昨天去参加adobe AIR发布会
昨天去参加adobe AIR发布会 2008-03-05 12:23 12547人阅读 评论(33) 收藏 举报 adobeairsliverlightwpf微软互联网 首先申明:我不是adobe雇佣 ...
- 《University Calculus》-chape4-极坐标与圆锥曲线-极坐标系下的面积与弧长
极坐标系下的面积: 在直角坐标系下一样,这里在极坐标系下,我们面临一个同样的问题:如何求解一个曲线围成的面积?虽然两种情况本质上是一样的,但是还是存在一些细小的区别. 在直角坐标系下中,我们是讨论一条 ...
- 长沙Uber优步司机奖励政策(1月18日~1月24日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- poj 3169 Layout
Layout Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8610 Accepted: 4147 Descriptio ...
- Java 8:不要再用循环了
本文由 ImportNew - 进林 翻译自 deadcoderising.欢迎加入翻译小组.转载请见文末要求. 正如我之前所写的,Java 8中的新功能特性改变了游戏规则.对Java开发者来说这是一 ...
- sql 数据字段类型
bit 整型 bit数据类型是整型,其值只能是0.1或空值.这种数据类型用于存储只有两种可能值的数据,如Yes 或No.True 或False .On 或Off. 注意:很省空间的一种数据类型, ...
- java代码实现对excel加密、解密(设置或去除打开密码)
使用jxcell组件来完成对excel加密.解密的功能. jxcell.jar[点击下载](此jar没有使用限制,你懂得) 具体代码如下: import java.io.IOException; im ...
- 【Android - 框架】之ORMLite的使用
Android中有很多操作SQLite数据库的框架,现在最常见.最常用的是ORMLite和GreenDAO.ORMLite相比与GreenDAO来说是一个轻量级的框架,而且学习成本相对较低.所以这个帖 ...
- hdu 2546 饭卡(DP)
很久以前做过这道题,晚上睡不着,看见nyist加了一个DP的比赛,就进来打个酱油. 这道题的点睛之笔是将最大值记录下来,然后将其值改为0.之后就是普通的背包了. #include<stdio.h ...
- Unit Test单元测试时如何模拟HttpContext
参考文章:http://blog.csdn.net/bclz_vs/article/details/6902638 http://www.cnblogs.com/PurpleTide/archive/ ...