x86内存地址转换

0x00 物理地址概念

用于内存芯片级的单元寻址,与处理器和CPU连接的地址总线相对应。物理地址是明确的、最终用在总线上的编号。

0x01 逻辑地址概念

逻辑地址指的是机器语言指令中,用来指定一个操作数或者是一条指令的地址。写汇编代码时,让CPU直接访问内存,这里所说的内存实际上就是逻辑地址。实际上用户层是不能直接访问物理内存的,只有内核级权限才能访问它。

在x86架构中,每个逻辑地址包括两部分:段(Segment)和偏移量(Offset)。

0x02 线性地址概念

也称为虚拟地址。在32位CPU中,它是32位的无符号整型,最大可以达到4G。在x86_64 CPU中目前最大可使用40位地址线,即最大可寻址1TB。

0x03 CPU与内存映射

CPU主要通过3种方式与外界交互:内存地址空间,I/O地址空间,还有中断。

前端总线把CPU与北桥连接起来(北桥则连接RAM内存、各种PCI设备,以及南桥)。每当CPU需要读写内存时,都会使用这条总线。在前端总线上传输的内存地址都是物理内存地址,编号从 0 开始一直到可用物理内存的最高端。这些数字被北桥映射到实际的内存条上。

在 CPU 内部,程序所使用的是逻辑内存地址,它必须被转换成物理地址后,才能用于实际内存访问。

0x04 内存地址转换与分段

XRg.png
从图中可以看到,
CPU先通过分段机制将代码中的逻辑地址翻译成线性地址(虚拟地址),再利用分页机制将线性地址(虚拟地址)翻译成物理地址,交给北桥寻址。

QQ截图20191207110557.png
对于每一个进程,系统分配4GB的虚拟内存(不管物理内存实际有多大),其中0X00000000至0X7FFFFFFF为用户进程空间,0X80000000至0XFFFFFFFF为系统空间,每一个进程都拥有这么个4G的虚拟地址地址空间。

用户区是每个进程真正独立的可用内存空间,进程中的绝大部分数据都保存在这一区域。
主要包括:应用程序代码、全局变量、所有线程的线程栈以及 加载的DLL代码等
每个进程的用户区的虚拟内存空间相互独立,一般不可以直接跨进程访问,这使得一个程序直接破坏另一个程序的可能性非常小。
内核区中的所有数据是所用进程共享的,是操作系统代码的驻地。
其中包括: 操作系统内核代码, 以及与线程调度、 内存管理、文件系统支持、网络支持、 设备驱动程序相关的代码。
该分区中所有代码和数据都被操作系统保护。用户模式代码无法直接访问和操作:如果应用程序直接对该内存空间内的地址访问,将会发生地址访问违规。

分段技术把虚拟地址空间映射到了物理地址空间,并且程序操作的是虚拟地址。
将用户程序地址空间分成若干个大小不等的段,每段可以定义一组相对完整的逻辑信息。每个段都从0开始编址,并采用一段连续的地址空间。
段的长度由相应的逻辑信息组的长度决定,因而各段长度不等。整个作业的地址空间是二维的。

段号4位,每个作业最多2的4次方=16段,表示段号从0000至1111;段内位移量12位,2的12次方=4k,表示每段的段内地址最大为4K(各段长度不同),从000000000000至111111111111

3段表示例:
段号 段长 起始地址 存取控制
0 1K 4096

1 4K 17500

2 2K 8192

分页技术仍然是一种虚拟地址空间到物理地址空间映射的机制。但是,粒度更加的小了。单位不是整个程序,而是某个“页”,一段虚拟地址空间组成的某一页映射到一段物理地址空间组成的某一页。
页号4位,每个作业最多2的4次方=16页,表示页号从0000至1111(24-1),页内位移量的位数表示页的大小,若页内位移量12位,则2的12次方=4k,页的大小为4k,页内地址从000000000000至111111111111

CPU在对内存进行操作时,内存管理单元MMU会将虚拟内存映射到物理内存上,所以出现的情况是虚拟内存的连续空间在实际的物理内存上并不一定连续,那么就需要一张表来记录虚拟内存与物理内存之间的映射关系,这就是分页技术中的页表。由于内存太大,页表可能会很大,为便于查找就把它再细分下,相邻的为一组,再加个组索引即有了两张页表了,第一张表来查属于哪一组的,再到那一组去查找更具体的。因此,X86采用二级页表的方式

-------------本文结束感谢您的阅读-------------
/*
*/