编程高手必学的内存知识
海纳
华为编译器高级专家,原 Huawei JDK 团队负责人
20674 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 33 讲
编程高手必学的内存知识
15
15
1.0x
00:00/00:00
登录|注册

02|聊聊x86体系架构中的实模式和保护模式

你好,我是海纳。
上一节课我们讲了虚拟内存的概念,分析了线性地址(虚拟地址)是如何映射到物理地址上的。
不过,在 x86 架构诞生之初,其实是没有虚拟内存的概念的。1978 年发行的 8086 芯片是 x86 架构的首款芯片,它在内存管理上使用的是直接访问物理内存的方式,这种工作方式,有一个专门的名称,那就是实模式(Real Mode)。上节课我们也曾简单提到过,直接访问物理内存的工作方式让程序员必须要关心自己使用的内存会不会与其他进程产生冲突,为程序员带来极大的心智负担。
后来,CPU 上就出现虚拟内存的概念,它可以将每个进程的地址空间都隔离开,极大地减轻了程序员的负担,同时由于页表项中有多种权限保护标志,极大地提高了应用程序的数据安全。所以人们把 CPU 的这种工作模式称为保护模式(Protection Mode)。
从实模式演进到保护模式,x86 体系架构的内存管理发生了重大的变化,最大的不同就体现在段式管理和中断的管理上。所以今天这节课,我们会围绕这两个重点,让你彻底理解 x86 体系架构下的内存管理演进。你也能通过这节课的学习,学会阅读 Linux 内核源码的段管理和中断管理的相关部分,还可以增加调试 coredump 文件的能力。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

x86架构中的实模式和保护模式是本文的主题。文章首先介绍了8086芯片的实模式,该模式下程序员需要直接访问物理内存,使用段寄存器来计算物理地址。然后,文章提到了保护模式的出现,它引入了虚拟内存的概念,隔离了每个进程的地址空间,减轻了程序员的负担,并提高了数据安全性。接着,文章详细讲解了8086中的实模式,包括寄存器位宽、段寄存器的作用、逻辑地址和物理地址的计算方式等。最后,文章提到了保护模式是实模式的进一步发展,带来了重大的内存管理变化,包括段式管理和中断的管理。 在i386芯片中,保护模式引入了全局描述符表(GDT)和页式管理,使得段式管理发生了重大变化。段寄存器进化成了段选择子,而GDT中的每一项都是一个全局描述符,存储了32位的段基址。保护模式的段描述符中记录了段的长度和属性,如P位、DPL、S位、G位和Type,增强了对段的保护能力。与此同时,文章还对比了段式管理和页式管理的优缺点,指出现代操作系统采用段式管理进行基本权限管理,而依赖页式管理进行内存的分配、回收和调度。 总的来说,本文详细介绍了8086实模式到i386保护模式下段式管理的演进,以及段式管理和页式管理的对比和现状。保护模式不仅带来了内存管理的重大变化,还影响了中断管理。读者通过本文可以全面理解x86体系架构下的内存管理演进,以及阅读Linux内核源码的相关部分和增强调试能力。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《编程高手必学的内存知识》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(27)

  • 最新
  • 精选
  • 慢动作
    没有段以后,代码权限是以什么为单位管理的?GDT是每个进程单独一份,IDT是系统独一份?

    作者回复: 1. 第一个问题,linux内核引入了vm_area_struct结构,通过软件的办法做了很多权限管理的事情,这个可以代替段的权限管理的部分工作;另外,每个页也有读写权限管理,所以硬件本身的页管理机制也代替了一些段的权限管理机制。 2. IDT是全局的,你已经理解了。GDT也是全局的。linux会使用GDT来区分内核代码段和内核数据段。每个进程单独的确实也有这种结构,叫做局部(local)表述符表,LDT才是和单个进程相关的表,其中的描述符的结构与全局描述符是完全一样的。由于它的结构和GDT非常像,我故意略去了。 3. 段选择子我没有展开讲它的结构,实际上,段选择子的第三位为0就表示要在GDT中找描述符,为1就在LDT中查找。所以你只要理解GDT就足够了。但既然你考虑到这里了,我就单独回答一下这个问题。 你思考得很深入,点赞!

    2021-10-27
    3
    20
  • 郑童文
    请问老师,IDT是储存在操作系统的内核内存空间的吗?GDT是存在进程的用户内存空间还是内核内存空间呢? 谢谢!

    作者回复: 好问题。gdt和idt都是由操作系统设置的。所以我们可以理解成是在内核空间里。但这仍然不准确。最准确的说法是由于gdtr和idtr里存的是物理地址,相当于操作系统从物理地址里扣了一块给gdt和idt。这块物理地址以后就不参与分配了。

    2021-10-27
    5
    7
  • Yun
    “实际上 64 位 CPU 的段式管理和 32 位的结构非常相似,惟一的区别是段描述符的段基址和段长度字段都被废弃了,也就是说不管你将段基址设置成什么,都会被 CPU 自动识别为 0”。 这句话里的“CPU自动识别为0”?记得是Linux内核将段基地址都设置为0,然后是的Linux本质上抛弃了段式管理,所以想请教一下,这里是CPU将段基址设置为0还是Linux内核来设置?或者说32位和64位还不一样?,谢谢

    作者回复: 32位linux先动的手,intel一看,你们写os的不按套路出牌啊,所以就干脆在设计64位cpu的时候把这块电路给扣了。

    2022-02-14
    6
  • 送过快递的码农
    保留段寄存器是不是为了向下兼容实模式啊?因为64位地址总线够大了,不需要段了。但是为了保证向下兼容性,段不做删除?纯属瞎猜

    作者回复: Good,这是很重要的一方面。是x86的设计哲学,但也给x86架构带来了巨大的包袱。

    2021-10-27
    5
  • 『SIGNIFICANT』
    java程序员一般不会接触到coredump这样的文件分析,一般也就是JVM调优,内存信息dump下来用工具查看,还有必要深入了解这些么

    作者回复: 不需要。java程序员的成长建议先学java类库,把算法和数据结构吃透是收益最大的。

    2021-12-06
    4
    3
  • .
    两顿饭钱买到很多知识,期待后面内存模型那块。以前看文章说理解x86内存模式是强类型,所以有部分标准内存屏障是不存在,我一脸懵了好多年。

    作者回复: OK,请继续关注,我们一定能讲清楚内存屏障是干嘛的。

    2021-11-15
    3
  • keepgoing
    老师,能理解为之后的i386中主要用段式管理(也就是GDT)来管理段类型的区分,比如代码段/数据段,用页式管理(所以GDT中的描述子G值一般都为1)来管理真正的物理内存和虚拟内存的映射吗? 如果这样来说的话,我理解段式管理主要来作类型的区分,在i386中程序员自己会去用逻辑地址寻址的场景是否会比较少,主要是什么场景会用到逻辑寻址呢。 初学小白,听了老师的课比较好奇,如有冒犯或理解不对的地方请老师多多包涵

    作者回复: 你的理解是对的。cpu的设计者是希望大家还继续使用段机制的,但是linux不按套路出牌,弱化了段的作用。linux主要使用页管理,所以,是的,后来的程序员不再使用逻辑地址了。

    2021-11-03
    4
    3
  • coder
    老师给的例子在x86上可以跑通,arm上不行

    作者回复: 你说得非常对!看了我们的前导课就会明白,x86和arm的寄存器都不一样,所以这个内嵌汇编只能在x86上运行。汇编是不能跨平台的。不过你倒是可以尝试修改一下哦,这就是跨架构移植了:)

    2021-10-27
    2
  • =
    内存碎片以前理解时,只考虑到了段式内存管理会有段间的内存碎片,一直没有考虑到页式内存管理的页内部的内存碎片问题。 海老师的这篇文章,从“16位CPU演化到32位CPU后内存管理的变化”的角度讲起,帮助我更好地理解了全局段描述符的问题,之前看x86CPU的GDT等知识,不知其所以然,但是今天从内存管理的角度来看,很清晰!

    作者回复: good。带着思考去阅读收获才能更大

    2022-01-10
    1
  • 乘风
    段式管理和页式管理都是针对的物理内存是吧,很虚拟内存没关系

    作者回复: 不是。它们都是内存管理的一种思路,既可以用于物理内存也可以用于虚拟内存。你可以这样理解虚拟内存:它和物理内存一样,也是一段地址空间,只是它还需要通过页表进行一次映射而已。对内存的管理,本质上就是对一段地址区间进行管理。再想想?

    2022-01-07
    1
收起评论
显示
设置
留言
27
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部