linux的页表为什么没有实现自映射

简介:

玩过windows内核的都应该知道windows为了节省4k的内存,实现了自映射,将页目录本身当作了一个页表来寻址4M的虚拟空间(将4M空间的虚 拟内存映射到物理内存),而这4m的虚拟地址空间恰恰就是从0xc0000000到0xc03FFFFF的空间,这一段空间正好是页表页目录的映射区域。下面我来说一下这怎么变成现实。 
首先有几点必须遵守的规则:1.一个页表映射的4m虚拟地址肯定是连续的;2.一个页表映射到的1024个4k的物理页不一定是连续的;3.实现自映射必须是页目录和页表结构一样。有了以上的规则,我们要想理解(或者自己实现一个)windows的自映射就必须理解实际上windows的页表虚拟地址都是 连续的,映射到0xc0000000到0xc03FFFFF,表现为一个页表数组,一共1024项,每项4096字节,一共正好4m,页目录作为这4m的 页表。我们反着想,如果页目录成为了这4m的页表,那么肯定映射0xc0000000到0xc03FFFFF的地址,我们将端点的两个地址分 解:11000000000000000000000000000000B和11000000001111111111111111111111B,仔细观察发现高10位是相等的,而这高10位正好是页目录项的索引,我们知道他是768,好了,页目录要作为第768页目录项对应的页表,现在这个页目录可以 作为一个页表插入到这个页表数组的第768项的位置了,它开始身兼两职了,CR3寄存器里面写的是它的物理地址,它作为页目录,此页面偏移768处也写入 了这个物理地址,它作为页表。 
现在考虑把这个页目录(页表)的虚拟映射地址换一下会怎样,别的页表不动。比如这个页目录映射到了0xdc000000这个虚拟地址(仅仅据个例子)。然 后分解地址1101110000 0000000000 000000000000,通过计算发现其对应于页目录的880项,那好吧,我把此页面880偏移改成此页面的物理地址,别的偏移处仍然指向 0xc0000000到0xc03FFFFF的虚拟地址对应的物理地址。看看会发生什么事情,如果把这个从0xc0000000到0xc03FFFFF游 离出来的页面当作页表的话,那么它所映射的虚拟地址应该连续,但是它自己是游离出来的,它的虚拟地址和别的页表的虚拟地址根本不连续,所以这样做是不可以的,也就是说对映射地址的连续性要求是一个必要的条件。windows之所以这么简单的实现了自映射,完全归功于它的设计思想,实际上一个设计并没有多么复杂,只要有了完备性,剩下的就是一个自然结果了,比如X系统是复杂的,而且它在unix出现很久以后才出现,但是unix却完美地支持了x系统,这就说 明unix很完备。windows的模块化作的很好,一致性作的也很好,它几乎将任何东西都标准化,每个进程的页表映射到同一个虚拟地址,在 windows看来,为每个进程提供一个一致的视图要比巧妙的杂糅式进程管理重要的多,所以它将虚拟地址空间作了很复杂的划分和规定。 
linux正好走了相反的路,它对于虚拟内存空间什么也没有规定,只是说了一下映射规则,提供了一套完备的机制,策略问题根本没有提及,内核虚存空间各个进程完全共享,各个数据结构散落在各处,内核空间仅仅提供了直接映射和高端映射的若干种映射规则和分配规则,至于说每个空间范围干什么用,linux只字 未提,所以说linux的页表可以散落在物理内存的任何地方,因为物理内存和虚拟内存在内核的很大一部分是一一映射的,所以上面的虚拟地址连续的要求就很难满足,比如这可能要求物理内存连续,在linux连续地址空间如此宝贵,浪费当作页表linux觉得这不值得,再说,页表可以随时分配,为什么要连续 呢?连续的话就要先预留4m页面,然后页表没有完全分配前会造成很多空洞,有几个进程能完全用完4m的页表呢?linux保守的回答了这个问题。我们看一 下代码就明白页表的分配了,代码来自最新的2.6.27内核:

int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,



 本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1274171

相关文章
|
2月前
|
Linux C++
Linux c/c++文件虚拟内存映射
这篇文章介绍了在Linux环境下,如何使用虚拟内存映射技术来提高文件读写的速度,并通过C/C++代码示例展示了文件映射的整个流程。
54 0
|
6月前
|
安全 Linux 数据安全/隐私保护
探索Linux命令newuidmap:用户ID映射的利器
`newuidmap`是Linux工具,用于在用户命名空间中设定UID映射,支持容器安全。它允许限定容器内进程的主机系统权限,确保数据安全和隔离。通过映射文件或命令行参数定义UID映射,提供灵活性和安全性。例如,为Docker容器设置映射,使进程能访问特定UID的数据文件。使用时需注意映射准确性、权限控制和避免映射过多UID。与其他工具如`newgidmap`配合使用以增强用户命名空间支持。
|
6月前
|
Linux 数据安全/隐私保护 Windows
linux 搭建cloudreve win映射网络驱动器WebDav
linux 搭建cloudreve win映射网络驱动器WebDav
171 2
|
6月前
|
监控 Linux
深入了解Linux的pmap命令:进程内存映射的利器
`pmap`是Linux下分析进程内存映射的工具,显示内存区域、权限、大小等信息。通过`/proc/[pid]/maps`获取数据,特点包括详细、实时和灵活。参数如`-x`显示扩展信息,`-d`显示设备。示例:`pmap -x 1234`查看进程1234的映射。注意权限、实时性和准确性。结合其他工具定期监控,排查内存问题。
|
6月前
|
存储 机器学习/深度学习 Linux
程序员必知:关于Linux内存寻址与页表处理的一些细节
程序员必知:关于Linux内存寻址与页表处理的一些细节
52 0
|
6月前
|
安全 Linux 数据处理
探索Linux命令newgidmap:用户命名空间与GID映射的桥梁
`newgidmap`是Linux工具,管理用户命名空间的GID映射,关键用于容器技术如Docker。它设置GID映射以确保隔离环境中进程的权限,避免ID冲突。通过映射文件或命令行参数设定主机GID到命名空间GID的对应,保证进程能安全访问文件。在Docker场景中,`newgidmap`配合映射文件调整进程PID的GID映射,确保数据处理任务有适当权限。使用时注意映射准确性、安全性和与其他工具的协同。
|
6月前
|
安全 数据挖掘 Linux
探索Linux命令newgidmap:用户命名空间与GID映射的桥梁
`newgidmap`是Linux中管理用户命名空间GID映射的工具,关键用于容器技术如Docker,保证进程在隔离环境中拥有适当权限。它设置GID映射,使容器进程能访问主机文件系统。主要特点包括灵活映射、安全性和易用性。通过指定PID和映射文件,如`newgidmap <PID> /path/to/gid_map.txt`,实现GID转换。使用时要注意映射准确性、安全性和与其他工具的配合。
|
7月前
|
存储 Linux 程序员
【Linux-14】进程地址空间&虚拟空间&页表——原理&知识点详解
【Linux-14】进程地址空间&虚拟空间&页表——原理&知识点详解
|
7月前
|
存储 算法 Linux
【Linux】线程的内核级理解&&详谈页表以及虚拟地址到物理地址之间的转化
【Linux】线程的内核级理解&&详谈页表以及虚拟地址到物理地址之间的转化
|
7月前
|
算法 安全 Linux
Linux 下共享内存方式 :System V共享内存、共享文件映射(mmap)、POSIX共享内存对比...
Linux 下共享内存方式 :System V共享内存、共享文件映射(mmap)、POSIX共享内存对比...
137 2