1. 首页
  2. > 香港公司注册 >

寄存器对地址用英语怎么说(寄存器英语怎么说)


本文主要根据 “Operating Systems: Three Easy Pieces” 第15章总结而来。


在本头条号之前的文章中有介绍,操作系统为了实现CPU虚拟化,采用的策略是:大部分情况下,地址让进程直接在CPU上运行,这样效率最高。但是为了不丧失对CPU的控制权,进程在进行系统调用时,或者操作系统设置的定时中断被触发时,操作系统又回重新夺回控制权。从这个层面看,高效和可控是现代操作系统设计的核心。内存虚拟化也不例外。


本节就来学习操作系统如何让进程能够高效并且灵活地访问内存,同时又对进程提供足够的保护!


基于硬件的地址翻译


基于硬件的地址翻译简称地址翻译,指的是对于每一次内存访问,硬件都会把虚拟地址(还记得你看见的地址都是虚拟地址吗?)翻译成物理地址,对通过物理地址才能读到真实的数据。当然,光凭硬件本身是做不到这些的,操作系统需要在关键点介入去设置硬件从而保证硬件能正确翻译,操作系统还必须管理内存,记录哪些内存是可用的,哪些内存已经被占用。


总之,通过操作系统和硬件的配合,让进程认为它拥有自己的一块内存来保存代码和数据,并且不会被破坏用。然而在完美的抽象背后,只有操作系统知道,随着CPU切换运行中的进程,很多进程实际上在共享内存。是操作系统把内存虚拟化让一切变得这么简单和美观。


为了实现内存虚拟化是非常复杂的,本文先做一些假设来简化目前的讨论,随着讨论的深入,这些假设都会被推翻,我们也会认识到内存虚拟化的所有技术。 * 假设一:用户(进程)的地址空间在物理内存中是连续说的。 * 假设二:地址空间的大小比较下,必须小于物理内存。 * 假设三:每一个地址空间的大小是相同的。


为什么需要地址翻译


基于上面的假设我们来看一个例子。请看下图的程序和使用objdump翻译成的汇编片段:



代码很简单,先加载内存中的值,然后加3,最后把计算后的值保存到内存中。从进程的角度看,代码和数据在它的地址空间内如下图所示:



可以看到,加3的代码从地址128开始(靠近代码段的顶端),变量x的值保存在地址15k的位置(靠近栈的底端),初始值是3000。当指令运行之后,从进程的角度看它会这样使用内存:


  1. 从128获取指令


  2. 执行指令(从15k的位置加载数据)


  3. 从132获取指令


  4. 执行指令(不用读取内存)


  5. 从英语135获取指令


  6. 执行指令(把数据写入15k的位置)


也就是说,进程认为它的地址空间是从0开始,最大是16k,所有的内存访问都必须在0-16k寄存器之间。然而,为了实现内存虚拟化,操作系统不一定会把进程放到物理内存0开始的位置。一个可能的视图如下图所示:



从图片来看,进程被放在了物理内存32k-48k的位置,16k-32k和48k-64k的位置还未被使用。那么问题来了,如何在进程无感知的情况下,把进程地址空间放到物理内存的指定位置呢?


基于硬件的动态重定位(或者是动态迁移)


前面的介绍都是背景,下面具体来看操作系统到怎么底是怎么实现怎么地址翻译的。这里就引出用了内存管理单元(memory management unit, MMU)中最基本的两个寄存器:基地址寄存机和上界寄存器,base and bounds。后续会使用英文,因为英文更能表达含英语义。


当进程最初开始运行的时候,操作系统会根据目前系统可用的内存情况,设置base寄存器的值。比如上面的例子进程的物理地址是从32k开始的,那么base寄存器会设置成32k。当进程想获取地址128的指令时,它会被翻译成 32k(32768) 128=32896,这样就能从物理地址里面取到真正的指令了。这就是所谓的地址翻译!重复一下公式: 物理地址 = 虚拟地址 + 基地址


那么bounds寄存器什么时候用呢?也是在进程最初运行的时候,操作系统预分配一定大小的内存给进程,bounds寄存器就会被设置成最大的值,比如上面的例子,被设置成16k。当进程试图引用大于16k的地址空间时,系统会抛出一个异常,这个异常就说是因为检查了bounds寄存器中的值。


从上面的流程可以看到,操作系统是在进程运行起来之后,根据系统可用的内存状对况来设置base and bounds,这个过程被称作动态重定位。与它相对的也有静态重定位,静态重定位发生在编译器,也就是说,程序编译完了就知道基地址是什么了。可想而知,静态重定位不具有移植性,在寄存器不同内存大小的系统就需要重新编译,就算内存大小相同也要根据系统可用的内存而定。所以,目前基本上操作系统都是基于MMU中的 base and bounds寄存器,使用动态重定向的技术。


操作系统的角色


上面说到的是硬件,特别是MMU起的作用,那么操作系统起了什么作用呢?


  • 首先,系统可用的内存列表是由操作系统维护的。有很多数据结构可以完成这个任务,随着我们的深入研究会不断介绍新的数据结构。这里我们先看最简单的数据结构叫空闲链表,free list。Free List很简单,把可用的内存分成很多块,每一块当作一个节点放到链表中。当新的进程来的时候,从列表中取一段内存给它,并把这段内存删掉。当进程退出后,再把内存块放到free list里面来。


  • 其次,在CPU做上下文切换的时候,操作系统必须要把base and bounds的数据也存储到PCB中。这样当进程重新被调度运行的时候,它依然能找到自己地址的代码和数据。


  • 第三,既然进程可以切换,base and bounds可以被保存和读取,那么在适当的时候,操作系统也可以移动进程在内存中的位置,只需要移动之后把base and bounds更新就可以了。这其实也是动态重定位的体现。


总结


解决这些问题就需要引入内存分页和分段的技术,这是后面会继续的内容。欢迎大家订阅我的头条号,第一时间收到更新,谢谢!


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至123456@qq.com 举报,一经查实,本站将立刻删除。

联系我们

工作日:9:30-18:30,节假日休息