当前位置: 代码迷 >> 综合 >> 2022-1-18
  详细解决方案

2022-1-18

热度:62   发布时间:2023-10-14 11:36:19.0

2022-1-18

  • 地址转换
    • 动态重定位
  • 分段
    • 我们引用哪个段
    • 共享支持
  • 空闲空间管理
    • 底层机制

地址转换

动态重定位

对于程序而言,其地址转换过程的不存在的,程序认为自己的地址就是开始于0kb,结束于固定大小,这就是地址转换的透明性,对cpu而言,实现程序地址到真实物理地址的转换很简单,cpu有两个寄存器,基址寄存器和界限寄存器,基址寄存器存储了程序的真实物理地址的起始点,界限寄存器存储了程序物理地址的终点

分段

如果我们直接将进程占用的内存连续设定,可能会出现很多未被使用的内存,造成资源浪费,这时我们需要将代码段,堆段和栈段分开给予内存
2022-1-18

我们引用哪个段

硬件在地址转换时使用段寄存器。它如何知道段内的偏移量,以及地址引用了哪个段?一种常见的方式,有时称为显式(explicit)方式,就是用虚拟地址的开头几位来标识不同的段,00代表代码段,01代表堆,10代表栈
2022-1-18
知道是哪个段后,使用基址+偏移量就可以获得物理内存地址了

在分段设置里,由于栈的占地是反向增长的,所以对栈的搜索有所不同
假设要访问虚拟地址 15KB,它应该映射到物理地址 27KB。该虚拟地址的二进制形式是:11 1100 0000 0000(十六进制 0x3C00)。硬件利用前两位(11)来指定段,但然后我们要处理偏移量 3KB。为了得到正确的反向偏移,我们必须从 3KB 中减去最大的段地址:在这个例子中,段可以是 4KB,因此正确的偏移量是 3KB 减去 4KB,即?1KB。只要用这个反向偏移量(?1KB)加上基址(28KB),就得到了正确的物理地址 27KB
2022-1-18

共享支持

随着分段机制的不断改进,系统设计人员很快意识到,通过再多一点的硬件支持,就能实现新的效率提升。具体来说,要节省内存,有时候在地址空间之间共享(share)某些内存段是有用的。
为了支持共享,需要一些额外的硬件支持,这就是保护位。基本为每个段增加了几个位,标识程序是否能够读写该段,或执行其中的代码。通过将代码段标记为只读,同样的代码可以被多个进程共享,而不用担心破坏隔离。
2022-1-18

空闲空间管理

在内存中如何分配用户或进程新申请的空间呢,这涉及空闲空间管理

底层机制

首先,操作系统有一个记录未被分配的内存的列表,称作空闲列表
2022-1-18
这时如果我们想申请一个大于10空间的内存,是肯定不会成功的,但是如果申请内存大小小于空闲内存大小,操作系统就会对空闲内存进行分割,将第一块分给用户,第二块留着
2022-1-18
在使用free或系统自动释放内存空间的时候,系统会查询被释放的空间左右是否有被分配,如果没被分配出去就将最新被释放的空间合并入之前的未被使用的空间
这里我们注意到,free函数的参数只有一个地址,而没有大小,那系统怎么知道该释放多大的空间呢,这由头部来实现
malloc函数在创建时,会带上一个头部,里面存储了分配的内存的大小

ptr=malloc(20);

2022-1-18
这样在用户调用free的时候,系统通过ptr-头部大小,就获得了hptr的位置,这也就得知了要释放的内存的大小了