Linux【多线程铺垫】之深度虚拟地址到物理地址的转换
引入
char* str="aasddad";
*str='A';----运行时报错
对待以上代码,如果我们不加const,会在编译时通过,运行时报错,这是因为,如果要修改该字符串常量,要通过虚拟地址找到对应的物理地址才能去修改。字符串常量是在已初始化数据和代码区之间的,当我们去查页表的时候得到其物理地址,但是它的权限只有“读”,没有“写”,而修改的操作是写操作,所以MMU会将修改的行为终止(硬件报错可参考我的【信号】文章)
深入认识地址空间与页表
- 地址空间是进程能看到的资源窗口:一个进程能看到代码区、共享区、内核区、堆栈区,大部分的资源都是在地址空间上看到的
- 页表决定进程真正拥有资源的情况:当前进程认为自己有了4GB,可是实际上用了多少由页表的映射关系决定最终能用多少物理资源
- 合理的对地址空间与页表进行资源划分,我们就可以对一个进程所有的资源进行分类:通过地址空间分为栈区、堆区…通过页表映射到不同的物理内存
虚拟地址到物理地址的转换
虚拟地址:32位系统下是32位, 物理内存:被划分成一块块的数据页,OS也要对物理内存做管理,先描述:struct
Page{//内存的属性——4KB},在组织:struct Page mem[],在OS中把物理内存一块块的数据页称为页框
磁盘上编译形成可执行程序的时候,也被划分成一个个4KB的区域称为页帧。当内存和磁盘进行数据交换时也就是以4KB大小为单位进行加载和保存的所以将数据加载到内存时,在文件系统级别,需要将数据从外设加载到内存以4KB为单位。最后,OS系统要管理内存除了结构匹配,还要有管理算法,linux常见的管理算法称为伙伴系统。
虚拟地址转成物理地址:
- 虚拟地址高10位对应第一级页表,共有2^10个,每一个地址指向一张页表;
- 虚拟地址次低10位,对应第二级页表,每个页表都有2的10个页表项,存放着指定页框的起始物理地址;
- 剩下的低12位虚拟地址刚好与页框的大小是相等的(4KB等于2的12次方字节),所以从物理地址的起始处+虚拟地址的低12位(2的12次方偏移量)作为页内偏移就在一个页框内找到了某个地址