在8086中
由于cpu有20位的地址总线,可寻址2^20=1M内存,而内部寄存器只有16位寻址方式,所以intel设计了段:偏移的方式来寻址。
段地址寄存器左移4位加上偏移即为物理地址。
8086中不存在页的概念,所以这种方式直接的到了物理地址。
把段:偏移称为逻辑地址。
80X86中地址总线为32位,可寻址4G,
80X86增加了保护模式,而它又由于需要兼容8086所以使用了分段和分页两种方式寻址。
逻辑地址-分段->线性地址-分页->物理地址
逻辑地址仍然采用段:偏移的方式来寻址,只不过这里的段内部结构已不同,它是GDT或者LDT中的一个索引。GDT或LDT中的一个项称为段描述符,有32位的基址和20位的界限以及一些属性,可以描述基址为0~4G,界限为0~1M或0~4G范围内的一个段(由描述符的G位确定),加上偏移,成为线性地址。
以寻代码段为例,逻辑地址CS:OFFSET到线性地址的转化如下:
根据CS中的指示位TI从gdtr或ldtr中找到gdt或ldt的基址,并索引到一个描述符,根据描述符找到这个段,段基址+OFFSET即为所要寻找的地址。
线性地址LINEAR_ADDR到物理地址的转化,假设使用二级页表:
在控制寄存器cr3中找到PDE表(4B*1024)基址,取LINEAR_ADDR高10位为索引找到一个PDE项,PDE指向一个PTE表(4B*1024)基址,取LINEAR_ADDR中间的10位在这个PTE表中作为索引找到一个PTE,这个PTE指向了一个物理页框,此物理页基址+LINEAR_ADDR低12位即得到物理地址。
三、 实验心得
深刻理解计算机内的内存管理是理解计算机工作的核心之一,虚拟内存,高速缓存,内存i/o,内存映射,mmu,DMA,缺页中断,用户空间,内核空间,共享内存,高端内存,运行特权级,多任务的切换,内存的分配算法诸多的概念都与内存有关,内存管理的好坏很大程度上决定了系统的性能。
linux采用突发式内存分配,当一个进程来到时,系统会尽可能多的分配内存来满足进程的要求,这使的进程的运行效率极高,大大提高了系统的运行速度。
为了兼容8086的地址格式段:偏移,x86可以采用分段与分页两种机制,实际上两种机制存在一定的冗余,在linux中为了更好的移植性和更方便的内存管理,尽量不使用分段而是分页。
linux中只设置了四个段,内核代码段,内核数据段,用户代码段,用户数据段,位于GDT中,对每一个进程而言,在GDT中有两项:TSS描述符和LDT描述符。
用户的线性地址空间为0~3G,内核的线性地址空间为3~4G。
其中又主要分成3部分,MEM_DMA:0~16M,用于DMA传输MEM_NORMAL:16~896M,用于映射至内核空间,MEM_HIGH:映射至用户空间。