05 | CPU工作模式:执行程序的三种模式
该思维导图由 AI 生成,仅供参考
从一段死循环的代码说起
- 深入了解
- 翻译
- 解释
- 总结
CPU工作模式的演变及特点 本文详细介绍了CPU的工作模式,包括实模式、保护模式和长模式。实模式下,CPU执行程序简单,不加区分地执行指令和访问内存,适用于资源有限的场景。保护模式通过扩展寄存器位宽和引入特权级等机制,实现对指令和资源的访问控制和内存保护。在保护模式下,CPU引入了控制寄存器和段描述符等新概念,提供更加灵活和安全的程序执行环境。文章还介绍了长模式(AMD64),包括寄存器和段描述符的特点。长模式弱化段模式管理,只保留了权限级别的检查,忽略了段基址和段长度,而地址的检查则交给了MMU。 切换到长模式的步骤包括准备长模式全局段描述符表、准备长模式下的MMU页表、加载GDTR寄存器、开启长模式和进行跳转。切换到长模式和切换保护模式的流程相似,但需要注意同时开启保护模式和分页模式。最后,文章提出了思考题,引导读者思考实模式下能寻址多大的内存空间。 总的来说,本文通过详细介绍CPU工作模式的演变和特点,为读者提供了对计算机CPU工作原理的重要参考价值。文章内容涵盖了实模式、保护模式和长模式的特点及切换步骤,对于系统开发人员和对CPU工作模式感兴趣的读者具有较高的技术含量和参考价值。
《操作系统实战 45 讲》,新⼈⾸单¥68
全部留言(163)
- 最新
- 精选
- Geek_a5edac置顶之前看过深入理解linux内核,但缺少模型上的分析,从书本从头看到尾反反复复最终似懂非懂,看了该系列整体上清晰多了,有了比较清晰的知识结构。而且因为之前有了解过相关概念,所以看此篇很快,倒没啥压力了哈哈
编辑回复: 6666,很高兴对你有帮助!看得出你的功底很扎实,继续加油
2021-05-3027 - Freddy置顶这节CPU三种工作模式,确实信息量比较大; 第一遍扫完后,发现好多细节都没有太懂; 第二遍精读,每句话,每个图,每行代码都一一理解后,再往下进行,龟速,需要很好的耐心,中间偶尔还要停顿信息,放松下大脑。这一边用了2-3个小时; 现在终于有感觉了; 看到长模式下,段描述符中不在有段基地址和段内偏移,就会去想那如何用段描述符定位内存中的数据呢? 这时就想到了操作系统里面的页面。。。 果然下面的文字就提到了MMU和TLB 激活了我多年没有用过的操作系统课知识点
作者回复: 你好,是的,你学习方法很好。值得点赞和推广
2021-05-2616 - Vic置顶看了今天的课程和同学们的留言让我百感交集。 人的一生时间有限,无法什么都做到极致。但在摸索的过程是可以什么都去碰一下,才知道自己喜欢什么。我以为我不是那么喜欢计算机。我不是本科,是念电机工程的,已算是很相近的,比起念化学或是文史哲商等。但我仍然用了一堵高墙将自己围住,说自己不是纯正计算机本科的。 二十年前刚开始工作时有机会接触8051控制器,是用8051的汇编代码,花了不少时间把中断、寄存器研究过、因为8051只有8位元,相对简单,但没有操作系统,我开始对操作系统有兴趣,就开始自学x86的操作系统,买书来看,但真的看不懂,当时也没有互联网上这么多讯息,还买了minix的书来看,英文的书有多了一层外文的障碍,因为工作忙,也没实际用到,就这么放下了。 最近看到老师的这专烂,让我想到之前放弃了的操作系统的学习。 老师讲的实在太好了,给100个赞都不够。因为他是亲身实践过,而且表达力极佳。 过去不懂的,开始有一点看得懂了。但是真的是单纯因为老师讲的好我才看得懂吗? 看到底下很多同学的留言,让我想起二十年前的自己。 这过程有点像是小学的数学学不明白,到了中学再回头看,竞然明白了。 其实是自己的理解增加了,我不想用聪明这个字,会误导很多人。 纠结在自己有没有天份。 我很认同老师在底下同学留言的回覆。 "不需要前置的知识","多看几遍","如果看到一个新东西 ,不要在意它叫什么,它叫什么都可以,而是要在意它是干什么的,它有什么作用。有了整体思路,再去扣细节。" 也不存在着需要什么条件,常常就是这种条件,自己把自己绊住了, 以为自己没有达到,就放弃了。或是就转移目标去完成那个条件,而忘了回来原来的操作系统的学习。 很多时候困难全是自己想出来的。觉得难,这是很正常的。 不必要对自己太严苛。可以稍微休息一下(我说稍微不是二十年),做一下别的事,再回来。 每个人的情况都不一定,没有一个固定的方法或是习惯,只有问你自己。 因为太难就放弃,那就太可惜了。可以慢一点没关系,不要放弃。 想想自己为什么来上这个课,想要从这个课得到什么? 如果是加薪,升官,学分或是为了下一门课会不会压力很大? 如果只是因为好奇,这看起来还挺有趣,想了解一下,会让你更挺得住这些困难。 因为有这些难点本来就很正常,克服了,弄懂了一个信心就会增加,就会继续前进, 如果一开始不去克服那个难点,选择逃避或是绕路,那永远就是在原地打转。 如果这一篇让你觉得鸡汤或是说教,那不是我的本意。只是将自己过去有感而发写下的。我也还在学习。 谢谢老师带来亲身实践后这么精彩的课程,也谢谢同学们对我的启发,共勉之~
作者回复: 你好,这个评论让我感到震撼,想必老哥之前也是认真研究过操作系统的人,才会有如此深刻的体会。一定是走了很多路才会有这样的启发和经验,我写这门的定位就是实战可能和学究派不同,我不讲虚的,只有让别人写出操作系统 ,这门课才达到了目标,也是对诸多同学的一个交付,谢谢你
2021-05-2616225 - neohope置顶稍微总结一下: 1、x86 CPU的位数越来越高,从16到32到64,每次进步都尽量的去兼容了之前的CPU架构,所以: A、16位时寻址能力不足,所以要借助额外的寄存器进行1M空间的寻址;32位时,每个程序都有自己独立的4G寻址空间,操作系统用低位的1G-2G,其余留给用户程序;64位后,暂时就遇不到寻址能力不足的事情了; B、前一代的寄存器尽量保留,不够用就扩展新的 C、寄存器的长度升级后,其低位可以兼容上一代的寄存器 2、CPU同时在安全性上也要提升,从只有实模式【可以随意执行全部CPU指令,内存可以直接通过物理地址访问,随意访问随意读写】,到了32的保护模式【将指令划分为ring0到ring3,CPU指令不是你想调用就能调用;内存不是你想访问就能访问,首先CPU要允许,而且操作系统允许】,而64的长模式在安全方面与32并没有本至区别; 3、从实模式到保护模式,访问内存时,需要访问的地址变大了,需要控制的内容变多了,于是引入了段描述符,所有的段描述符组成了描述符表,包括唯一的全局描述符GDT和多个局部描述符号LDT。GDT是操作系统特供,要重点关注。CPU寻址的时候,要通过段寄存器+GDTR寄存器定位到的内存中的描述符,判断是否允许访问。然后,再根据段描述符中地址进行访问。 4、同时内存中内存管理有段、页、段页三种常用模式。一般在应用层,程序员感受不太到,操作系统全给咱们做完了。 5、中断,其实是通过硬件或软件方式告诉CPU,来执行一段特殊的代码。比如咱们键盘输入,就是通过硬件中断的方式,告知操作系统的。在实模式下,中断是直接执行的。但到了保护模式和长模式下,就要特权级别校验通过才能执行,所以引入了中断门进行控制。在ring3调用中断一般是要通过操作系统切换到内核态ring0进行的,与内存类似,要通过中断向量表,确认中断门中权限是否允许,然后定位到指定代码执行。 6、BIOS引导后,系统直接进入最简单、特权最大的实模式;而后告知CPU,切换到保护模式,并运行在ring0。后续的用户进程,一般就在ring3,想执行特权指令要通过操作系统来执行。
编辑回复: 很感谢你的分享和总结,66666~
2021-05-234155 - 李军置顶汇编看不懂,还有x86平台也不懂,请问可以从哪里入手下?
编辑回复: 小编指路,根据群聊分享,汇编可以参考《汇编程序设计》(王爽)。 不用太过担心,汇编只占很少一部分,先理解课程整体思路。另外,你现在不理解具体寄存器的细节,也不会影响对整个课程的学习,别慌。
2021-05-1952 - 李军置顶搞java的我,表示没看懂
编辑回复: 如果看到一个新东西 ,不要在意它叫什么,它叫什么都可以,而是要在意它是干什么的,它有什么作用。有了整体思路,再去扣细节。
2021-05-191059 - pedro置顶这篇文章信息量很大,但是问题比较简单,我先回答一下问题吧。 实模式下的寻址空间跟地址总线的个数是密切相关的,早期的 x86 物理机,虽然寄存器是 16 位,但是地址总线却有 20 根,根据计算 2^20 = 1M,寻址空间肯定得有 1M 啊,但是寄存器只有 16 位,即 2^16,没有这么大的空间啊,臣妾办不到啊~ 那怎么办呢?聪明的 intel 工程师(挖坑师)想到了一个办法,即段寄存器左移 4 位,然后加上另外一个通用寄存器的值就可以组合出这个 20 位了,即 2^16 * 2^4 + 2*16,哦嚯一下子组装出来了。 这样 20 根地址总线都用上了,得到了 1M 的寻址空间,可把工程师给乐坏了。 但是,后面的事情大家都知道了,16 位不够了,32 位也不够了,在 64 位的情况下,完全不用考虑地址空间的大小问题了,变成了内存不够的问题了,而这个时候,保护模式下的虚拟地址映射又完美解决了这个问题(虚拟地址后面有),哟嚯,又把 intel 的这群挖坑师给乐坏了。
作者回复: 哈哈
2021-05-1924167 - 云师兄置顶内容硬核,已啃三遍!
作者回复: 坚持 就会 明白 不错哦
2021-05-1912 - 马杰看到后面,回头再看一遍,记点笔记。 实模式,保护模式,长模式,逐渐演进 1、实模式: (1)代码段地址+左移4位+ IP = 取指 数据段+左移4位+ 通用寄存器值 = 数据地址 栈段SS+左移4位 + SP = 栈地址 (2)实模式中断: 中断号+ IDTR 寄存器(指向中断表的地址和长度) ---> 根据中断号,找到中断表中的对应条目 ---> 解析出中断函数基地址填充CS、中断函数偏移填充IP ---> 响应中断。 2、保护模式: (1)保护模式寄存器:通用寄存器,IP,SP 16位->32位。添加了EFLAGS cpu标志寄存器和几个cpu控制寄存器。 CS DS SS 中改为存放内存段的索引,用于寻找内存中的段描述符。 (2)保护模式下,R0 -- R3的特权级别访问。通过内存中存放64位段描述符实现特权划分,段地址寻址。 CS | DS | SS (段描述符索引)+ GDTR(指向全局段描述符表基地址) -- > 找到段描述符 --> 解析代码段还是数据段,地址,访问权限 其中影子寄存器 : 通过硬件实现,是段描述符的高速缓存, 防止反复读内存,提高效率。 权限问题:当前执行程序的CS RPL、SS RPL = CPL, 要访问的段描述符中拿到DPL, CPL > DPL 禁止程序访问目标段, CPL <= DPL , 可以访问 (3)保护模式的平坦模型: 段基址为0,段长度为4G的特殊段管理模式,规避历史原因导致的分段模型缺陷。 (4)保护模式中断:中断号+ IDTR 寄存器(指向中断表) ---> 根据中断号,找到中断表指向的内存中的中断门描述符 ---> 中断门和中断描述符中段选择子的权限检查--> 中断门描述符中目标代码段选择子填充CS, 目标代码段偏移填充EIP ---> 响应中断。 权限问题:当前CPL小于等于中断门DPL,才可进中断门,当前CPL,大于段选择子的DPL,则设置CPL=段选择子DPL。 例:当前运行代码CPL=R3级别,遇R3中断门进门,执行特权级中断程序R0,此时CRL=R0。 (5) 切换保护模式: 准备全局描述附表GDT, GDTR指向GDT, 设置CR0开启保护模式, 执行长跳转,CPU根据8索引值索引GDT中第二条数据,加载CS 3、长模式: (1)寄存器扩展到64位 (2)长模式段描述符, L=1,D/B=0 时是64 位代码段, L , D/B, 无效是数据段 (3)长模式中断:中断们描述符比保护模式多了8字节64位,用于存放64位的目标代码段偏移多出来的高32位。 其他中断过程同保护模式。 (4)长模式切换:准备长模式全局段描述符表, 准备长模式下的MMU页表,开启分页模式 CR3指向页表物理地址 GDTR指向全局段描述符表 IA32_EFER寄存器第8位开启长模式,CR0寄存器= 0x31开启保护模式和分页模式 进行跳转,索引GDT, 加载 CS 段寄存器,刷新其影子寄存器 (5)长模式弱化段模式管理,只保留了权限级别的检查,忽略了段基址和段长度,而地址的检查则交给了 MMU,分页管理。
作者回复: 对的,总结到位
2021-07-14426 - 尼欧建議大家讀讀李忠老師的《穿越計算機的迷霧》,學習一點硬件原理,對後續學習會有很大幫助。很薄的小冊子,三兩天就能讀完。
作者回复: 66666 这个不错
2021-05-19423