首页 > 代码库 > 2.内存寻址

2.内存寻址

  • 内存地址 
    1. 三种内存地址:1)逻辑地址(机器指令中操作数或指令的地址) 分段单元 2)线性地址(虚拟地址)分页单元 3)物理地址(用于内存芯片级内存单元寻址
    2. 多CPU时,共享同一内存,RAM芯片由独立的CPU并发访问; 由内存仲裁器保证RAM的读写的串行执行
         
  • Linux中的分段 
    1. 80X86才使用分段(把程序划分为逻辑相关的实体),Linux更喜欢使用分页(当所有进程使用相同的段Register值时,它们共享同样的一组线性地址,这样内存管理简单; RISC对分段的支持有限.).
    2. 两者都划分进程的物理地址空间:分段可以给每一个进程分配不同的线性地址空间,而分页可以把同一线性地址空间映射到不同的物理空间.
    3. 段选择符由宏__USER/KERNEL_CS/DS定义.对内核代码寻址,吧__KERNEL_CS宏产生的值装入cs寄存器即可.这样执行指令时,只需指定逻辑地址的偏移部分,段选择符已经隐含在寄存器内.
    4. 所有段(内核/用户的数据/代码段)的Base=oX0000000,即逻辑地址(的偏移量字段值)=线性地址(的值).所有进程使用相同的逻辑地址.
    5. 每个CPU一个GDT,会插入未使用的项使得经常一起访问的描述符能够处于同一32字节的硬件Cache中; 大多数用户态APP不适用局部描述符表,所以定义了一个缺省的LDT供进程共享,同时进程可以创建自己的LDT.
         
  • 硬件中的分页 
    1. 分页单元的一个关键任务就是把所请求的访问类型与现行地址的访问权限相比较,如果访问无效,产生一个缺页异常.
    2. 页: 线性地址被分为固定长为单位的页,页内连续的线性地址被映射到连续的物理地址中,内核仅需为页指定物理地址和存取权限,提高了效率.
    3. 页框: 相应地,把RAM也分为固定长度的页框(物理页),一个页框包含一个页(长度一致).
    4. 页表: 把线性地址映射到物理地址的数据结构.存放于主存中
    5. CPU通过设置cr0寄存器的PG=0标志启动线性地址到物理地址的翻译
    6. 常规分页 
      1. 页Size=4KB.从而32位的线性地址= Directory(10b:目录)+ Table(10b:页表)+ Offset(低12b:偏移量)
      2. 转换分为两步,每一步基于一种转换表.使用二级模式为了减少每个进程页所需的RAM的数量.二级模式只为进程实际使用的那些虚拟内存区请求页表来减少内存容量.
      3. 每个活动进程都有一个页目录,但是仅在进程实际需要一个页表时才给该页表分配RAM.
    7. 扩展分页: 页框Size=4MB.用于把大段连续的线性地址转换成相应的物理地址.不适用中间页表.32b线性地址=Directory(10)+Offset(22)
    8. 64位系统中的分页: 使用了额外的分页基本.不然的话每个进程的页目录和页表含有的表项太多.
    9. 物理地址扩展(PAE)分页机制 
      1. CPU所支持的RAM容量受地址总线上的管脚数限制,将该数从32改为36即可为2(36)=64GB.
      2. PAE机制:1)64GB的RAM分为2(24)个页框,页表项的物理地址字段从20变为24位.所以PAE页表项=12个标志位+24个物理地址位=36,页表项Size=64(>32).所以一个4KB的页表包含512个页表而非1024个.
      3. 2)引入页目录指针表(PDPT)的级别,由4个64位表项组成.
      4. 3)cr3控制寄存器含有一个27位的PDPT的基地址,因PDPT在RAM的前4GB中,并在32字节的倍数上对其,所以27可以表示其基地址
      5. 解释32位线性地址(4KB/2MB的页):1)cr3指向PDPT; 2)31-30指向PDPT中4个项之一; 3)29-21指向页目录中512个项中的一个; 4)20-12指向页表512项之一+11-0为4KB页内Offset/20-0为2MB页中Offset.
      6. PAE的主要问题是线性地址仍是32位.并没有扩大进程的线性地址空间,而只处理物理地址.内核编程人员必须用同一线性地址映射不同的RAM区.
      7. 由于只有内核才能修改进程的页表,所以用户态下的进程不能使用>4GB的物理地址; 但内核能够使用更多的物理地址从而增加了系统中的进程数量.
    10. 硬件Cache 
      1. 由行(几十个连续的字节)组成.其位于分页单元和主内存之间.由硬件Cache内存(真正的行)+Cache控制器(表项数据.一个表项(标签(辨别行映射的内存单元)+标志)对应一个行)组成
      2. 类型: 直接映射/充分关联/N-路组关联,来将主存中的一个行,关联到Cache中的一个行.
      3. 写策略:通写(同时写RAM和行,一般为了效率,关闭Cache; 回写:只写Cache的行,当CPU没有命中时,Cache的行被写回到内存中.
      4. 一个CPU一个Cache,需要使用高速缓存侦听(snooping)来同步他们的内容.
      5. Pentium CPU可以为每一个页框指定Cache策略,Linux忽略之,使得所有的页框都启用Cache,且回写策略.
    11. 转换后援缓冲器(TLB): 加速线性地址的转化.物理地址经过一次转化后放于TLB表项内.其每个CPU都有一个,但是不必同步,因为运行在现有CPU上的进程可以使同一线性地址于不同的物理地址关联.
         
  • Linux中的分页 
    1. 组成:页全局目录+页上级目录+页中间目录+页表. 并在32位系统中将页中间目录和页上级目标级别的位设置为0来对应.
    2. 物理内存布局: Linux内核安装于RAM的第二个MB开始.原因:页框0由BIOS使用; 640KB~1MB为洞(物理地址被保留但不能被使用).布局=内核代码+已初始化过的Data+未初始化过的Data.
    3. 进程页表:线性地址空间,用户态 < oXc000000, 内核态 > oXc0000000.
    4. 内核页表