深入理解Linux内核-第二章内存寻址

内存寻址
    内存寻址
        逻辑地址:(段:偏移量)
        线性地址:也称虚拟地址
        物理地址
        CPU的内存控制单元先将逻辑地址转换为线性地址(分段单元);
然后将线性地址转换为物理地址(分页单元)。
是程序分段。
    硬件中的分段
        段选择符:存放在段寄存器中,包含段描述符的索引index(13),TI标志,请求者权级(2)
        段描述符:存放在全局描述符表中(GTD)or局部描述符表(LDT);每个描述符8个字节,描述了段的特征(大小,首地址,权限等)。GTD和LDT存放在主存中的地址的大小放在gdtr和ldtr中。
        分段单元(硬件自动完成):1)检测TI字段,决定从gdtr还是ldtr中取出描述符;2)将段选择符的index字段乘以8与gdtr或ldtr中的值相加得到段选择符的地址;3)将段选择符的base字段和偏移量相加得到线性地址。前两步只需要在段寄存器的内容改变时执行。
        当每一个段选择符被装入段寄存器时,段描述符被装入相应的非编程寄存器中;分段单元可以直接从非编程寄存器中取出段描述符中的段基址;
    Linux中的分段
        核心:分段可以给每一个进程分配不同的线性地址空间,而分页可以把同一个线性地址映射到不同的物理内存中;Linux所有进程共享同一组线性地址(即所有段描述符的base都为0),但是段描述符的其它字段值不一样;Linux下面逻辑地址和线性地址一样;
        Linux的GDT:每个CPU都有一个GDT;具体见书本(49页)
        Linux的LDT:用户态进程一般不使用LDT
        补充:TTS段:每一个CPU有一个TSS段;TSS段的线性地址空间是内核数据段线性地址空间的一个小子集;TSS段用于保存CPU寄存器的内容。
    硬件中的分页
        常规分页:两级分页;页目录的物理地址存放在CR3寄存器中;每个进程都必须分配一个页目录;页表不需要全部分配,只需要分配使用的页表;页目录项和页表项有相同的结构(32位)。结论:页表,页目录的大小都是一页(4K)
        扩展分页:允许页框的大小为4K;不使用两级分页,不需要页表;
        硬件高速缓存:插在分页单元和主内存之间,CPU自带硬件;
        转换后援缓冲器(TBL):用于保存一组线性地址对应的物理地址;加快物理地址的内存访问;CPU自带硬件;当CR3寄存器内容被修改时,TLB自动无效。
        概要
    Linux中的分页
        使用四级分页的模型;每一个进程都有自己的页全局目录表和自己的页表集;发生进程切换时,把CR3的内容保存到前一个进程描述符中,把切换进的进程描述的页全局目录地址存到CR3中。
        物理内存布局:Linux内核加载进内存的第二个MB位置;第一个MB存放:页框0存放BIOS检测到的硬件系统配置;其他页框用于不同用途保留。
        进程页表:页全局目录表的第一部分目录项的线性地址映射小于PAGE_OFFEST;第二部分的表项都映射内核线性地址空间,所有进程都一样。
        内核页表:内核维持一组自己使用的页表,驻留在所谓的主内核页全局目录中。
        临时内核页表:分页的第一个阶段目标是允许实模式和保护模式下都可以对RAM空间的前8M内存寻址;前8M包含了内核代码段、数据段、临时页表和128KB;临时页表紧接着_end存放;临时页全局目录存放在swapper_pg_dir变量中。swapper_pg_dir表项只有四项被初始化为非0.(0,1,0x300,0x301项)
        内核最终页表:必须把0xc000000000开始的线性地址转化为从0开始的物理地址;因此swapper_pg_dir的全局目录表项必须重新初始化。
        固定映射的线性地址:内核初试部分的线性地址和从0开始的物理内存映射,至少还有128MB的的线性地址留作他用。
        处理硬件高速缓存和TLB(内核如何使用硬件高速缓存来使得性能最佳):一个数据结构中最常用的字段放在改数据结构中的低偏移部分,以便它们处于同一高速缓存行中;当为一大组数据结构分配内存时,内核试图把他们都放在内存中,以便所有高速缓存行按统一方式处理。
        概要


版权声明:本文为weixin_38812277原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。