06 | 虚幻与真实:程序中的地址如何转换?

2021-05-21 LMOS
《操作系统实战 45 讲》
课程介绍


讲述:陈晨

时长:大小21.00M


你好,我是 LMOS。
从前面的课程我们得知,CPU 执行程序、处理数据都要和内存打交道,这个打交道的方式就是内存地址。
读取指令、读写数据都需要首先告诉内存芯片:hi,内存老哥请你把 0x10000 地址处的数据交给我……hi,内存老哥,我已经计算完成,请让我把结果写回 0x200000 地址的空间。这些地址存在于代码指令字段后的常数,或者存在于某个寄存器中。
今天,我们就来专门研究一下程序中的地址。说起程序中的地址,不知道你是否好奇过,为啥系统设计者要引入虚拟地址呢?
我会先带你从一个多程序并发的场景热身,一起思考这会导致哪些问题,为什么能用虚拟地址解决这些问题。
搞懂原理之后,我还会带你一起探索虚拟地址和物理地址的关系和转换机制。在后面的课里...

展开全文
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。

精选留言

  • pedro
    置顶
    2021-05-21
    😃又是信息量爆炸的一节,不过读下来也是挺爽的。这里我替很多同学说明一下,虚拟地址中的页内偏移才是决定页大小和多级目录的核心点,页内偏移必须与页大小保持一致,这样才能保证寻址可以找到页内的每一个地址。 对于思考题,其实也比较简单,文中也谈到了,实模式下多个任务共享所有地址空间太危险,因此才有了保护模式,保护模式下的分页模式是一个巨大的创新。 对于每个进程而言,它会误认为(被操作系统欺骗)自己独有所有地址空间,因此它访问地址是不会考虑任何问题的,可是这个地址是虚拟地址,待被MMU翻译后会得到对应的页表,而这个页表由操作系统管理,不同的进程拥有不同的页表,也因此产生了进程地址空间隔离,但是多个进程也是可以共享某个页表,这也是进程通信(IPC)的根本手段。
    展开

    作者回复: 你学到位了 66666

    共 20 条评论
    104
  • Geek_4b6813
    置顶
    2021-06-26
    配合之前的现代操作系统的学习有一些收获不知道对或不对 虚拟内存实际上是存储器地址空间抽象的一种实现。从进程的角度看起来就好像自己独占了整个内存,链接器链接编译产物的时候只需要从0地址开始做变量和函数地址的替换,不需要关心自己是否会把其他进程的内存单元给污染。地址空间是进程可以访问的所有内存单元的集合 而虚拟内存的实现带来的好处只要有 1.利用程序的局部性原理,使用时间换空间,通过不断地淘汰/加载页表项就可以模拟出巨大的内存。 2.使用mmu并行计算的能力,减少了基址寄存器和界限寄存器的add和compare操作。 但是软件开发是没有银弹的,虚拟内存同时也带来了一些实现上的挑战 1.从虚拟内存到物理内存的映射必须要尽可能快,不然访存的时候反而会成为指令执行速度的瓶颈,这点现代操作系统大多通过在内核中维护一个tlb做页表-页框的映射缓存表来实现,这里是空间换时间。 2.随着虚拟内存的增加,比如要表示4GB的虚拟内存,以4KB的页面大小为例,共需要4GB/4KB= 2^20,而每个页表项需要32位即是4个字节大小,一个进程的页表总共为2^20*4 = 4194304(字节) = 4MB。 假设4核cpu同时运行不同的进程,操作系统在内核中至少需要维护16MB的页表。看起好像很小对不对,大家可以尝试按64位内存总线去换算。所以为了避免一次性加载大量页表到内存中,会采用多级页表策略。如老师文中描述的,一次只加载一级页表到内存中,并且可以选择淘汰上一级页表,通过多次映射的方法来避免大页表,到这里又是时间换空间了。 而对于老师说的,mmu无法映射物理地址时,有几种原因 1.访问了受内核保护的页面,或者访问了只读的页面(比如c语言中存储字符串字面量和const变量的段),此时内核会抛出段错误 2.页面和页框没有产生映射关系,但是数据页已经被其他进程加载到内存中了,此时只需要建立页面和页框的映射关系,称为次级缺页中断 3.页面和页框没有产生映射关系,数据页也没有被加载到内存中(在磁盘上),此时需要发生磁盘io从磁盘中加载页到内存中,还需要建立页面和页框的映射关系,称为严重缺页中断。 除了第一点,第二第三都会以内核降低自身运行速度来修复,也就是老师说的,通过中断形成页表映射,然后再重新执行引起中断的命令(此时数据页已经在内存中并且建立映射关系了)。
    展开

    作者回复: 是的,大写6666,太厉害了

    共 7 条评论
    58
  • 宇宙的琴弦
    置顶
    2021-05-22
    看同学们的评论,也让人收获不少,喜欢这样的氛围!感谢!

    作者回复: 谢谢,希望以我的微薄技术能帮到大家

    
    11
  • 一省吾身
    置顶
    2022-05-06
    信息量爆炸,细节深挖不动,大方向上的个人理解和收获: 为什么需要虚拟地址: 实模式中如果运行多道程序有一些问题需要解决: 地址冲突 控制互相访问 代码占用的空间大到物理内存放不下怎么办 不同计算机的容量各不相同,方案如何全部支持 给每个程序一个私有的连续的独立的虚拟的地址空间,和计算机无关,和其它程序无关. 解决思路: 将虚拟地址与物理地址分离,让应用程序从实际的物理内存中解耦出来,增加中间层MMU去做地址转换,对程序透明. MMU: 设计思路: 虚拟地址到物理地址直接做映射,则映射关系大到无法接收,维护成本太高. 虚拟段基址映射到物理段基址,看似可以,但是段长度各不相同,并且粒度可能会很大. 因此把虚拟地址和物理地址空间都分成同等大小的块,按照虚拟页和物理页进行映射和转换,地址转换表中存放虚拟页地址对应的物理页地址即可. 实现思路: 纯硬件实现没有灵活性,用软件实现太低效,因此使用软硬件结合的方式. 用硬件电路逻辑实现地址转换器件,接受虚拟地址和地址关系转换表,输出物理地址. 为什么需要多级页表: 每个进程都有自己的页表,多级页表可以省掉大量未映射页表占用的空间,为null则说明后面的页都没有使用. 虚拟地址由虚拟页号和虚拟页号偏移组成,多级页表查找时可以使用索引.
    展开

    作者回复: 嗯嗯 理解的不错

    
    
  • blentle
    2021-05-21
    多个进程隔离应该是操作系统进行任务切换时会改写CPU的页表基地址寄存器为当前被运行进程的页表基地址吧!

    作者回复: 是的 是的

    共 3 条评论
    27
  • 黎
    2021-05-21
    一脸懵逼的进来,一头雾水的出去

    作者回复: 不要着急 等后面的课程出来了 就明白了

    共 4 条评论
    21
  • springXu
    2021-05-21
    每一个进程会有不同的页表内容。 在32位的windows系统中虚拟地址2g到4g空间都是系统函数调用空间,这部分的对应的物理空间是同一块区域。但低端虚拟内存空间各个进程空间对应的物理地址不相同,所以进程间的页表有部分相同,有部分是不同的。 另外32位的xp系统是可以设置成1g的系统内存空间的,也就是进程的私有空间由0到2g的范围变成了0到3g的虚拟空间。与上面的描述又有些变化了。 到了64位好像是128T的虚拟内存空间的是进程私有虚拟内存空间。
    展开

    作者回复: 你说的对 6666

    共 4 条评论
    9
  • Geek_9627ff
    2021-08-28
    这课也太顶了吧,撒哈拉沙漠都没这课干

    编辑回复: 写操作系统,有一些硬核的硬件知识必须补补课,加油加油~

    
    5
  • xzy
    2021-08-07
    有个疑问,现代CPU都是多核的,那么一个4核的CPU是共享一个MMU,还是每个核心都有自己的MMU,有4个MMU呢?

    作者回复: 都 有自己的

    共 3 条评论
    6
  • 天涯海角
    2021-05-29
    请教几个问题: 1.不同的进程拥有不同的页表,这句怎么理解?如何实现的?页表不是cpu的工作模式确定了,地址转换关系表也就确定了,页表也就确定了的吗? 2.操作系统控制进程页表是怎么实现的? 3.链接器生成的虚拟地址与在应用程序运行时使用%p打印的虚拟地址是同一个吗?或者说应用程序发生段错误 知道了地址,可以通过反汇编来定位吗? 谢谢
    展开

    作者回复: 在后面的课程中都有答案

    共 3 条评论
    4
  • 罗 乾 林
    2021-05-21
    不同进程分配不同的pid,相同的虚拟地址将被映射到不同的物理地址上

    作者回复: 你好 ,不同的进程 有不同的页表

    
    4
  • 尼欧
    2021-05-21
    打卡

    编辑回复: 加油。锲而不舍,金石可镂。

    
    4
  • 三生
    2021-09-06
    分段的平坦模式,就是将段基地址设置为0然后直接加上偏移地址,0 + 段内偏移=线性地址=逻辑地址,分段机制等于没有使用(检查等还是使用的),而是直接使用了分页

    作者回复: 是的,你理解的很正确

    
    3
  • Paul Shan
    2021-05-23
    思考题 每个程序对应的CR3内容不同,进而映射也不相同,同样的虚拟地址被映射到不同的物理地址。

    作者回复: 你好。正确 正确

    共 2 条评论
    4
  • 疯码
    2022-01-11
    “首先来看看保护模式下的分页,保护模式下只有 32 位地址空间,最多 4GB-1 大小的空间。” 为什么是4GB减去1呢,减去1的意思是0地址有硬性规定不能用么

    作者回复: 地址是从0开始计算的

    
    2
  • linuxery
    2021-10-16
    任务切换的时候,也就是调度的时候是不会切换cr3控制器里面的gdt的,切换的应该是ldt里面的。 再者,系统上电后先bios自检,自检完成后bios将跳到os引导区,一般是:0x7c00,当然,bios需要根据设置去逐个寻找引导驱动器,说白了就是cdrom,硬盘啊这些,一般磁盘的引导都在7c00,然后开始执行os引导程序,引导程序一般在磁盘上0磁道,0磁头,1扇区,一般大小为512字节,并以0x55AA结束。这里还需要考虑实模式向保护模式的转换,也就是注备必要的gdt,并让gdtr指向gdt。 这些老师好像没涉及,而用后面的grub来代替完成了。这是我在大学(2002年)写第一版os时候需要考虑的,时间久了,有些不准确,见谅。有些不对,请不吝指教。谢谢!!
    展开

    作者回复: CPU模式转换我在硬件部分说了 机器引导我用GRUB 所以没有细节

    
    2
  • 安安
    2021-10-20
    这节干货满满的,简直太干了,有些消化不了,得补充一下水分,再继续学😜😜

    作者回复: 那就补充一下再来学习

    
    1
  • Manfestain
    2021-07-08
    连接器每次分配虚拟地址时都是从1开始,那每个进程的虚拟地址应该是相同的吧,按照虚拟地址被分为四个短,逐段索引找到最终的物理地址,那所有程序找到的物理地址应该也一样了,是不是还有什么东西控制每个虚拟地址中的页,这样不同的进程才会拥有自己的内存空间

    作者回复: MMU啊

    
    1
  • Geek_2378fa
    2021-06-30
    虽然有点开始吃力了,但读下来挺让人兴奋的

    作者回复: 应该还好吧

    
    1
  • Geek_e2256b
    2021-06-14
    我的理解就是多级页表,从第一个跳到最后一个 最后的页内偏移对应了我们所说的4KB/2MB/4MB页表 可以配合《深入理解计算机系统》第9章以及youtube上老师的讲解进行观看

    作者回复: 嗯嗯 理解不错

    
    1