Linux页表中虚拟内存地址如何映射到硬盘数据块地址?Linux 内核模块如何直接访问物理地址获取内容
当页表发现虚拟内存的内容不在物理内存中会发生缺页,这时候,需要把硬盘上某个数据块读入内存,并修改页表。问题是,内核怎么指定需要去读取磁盘上的哪①个数据块呢?
虚拟内存如果映射的是物理内存,那么页表的内容是物理内存地址,那么如果映射的是磁盘数据块,那么页表的内容是什么呢?
谢邀 @逸文奥特曼
Linux页表中虚拟内存地址如何映射到硬盘数据块地址? 显然这个问题是不对的,CPU没有直接访问磁盘的能力,CPU页表里填的永远是内存地址,除非这个磁盘是挂到地址总线上,而且可以像普通内存①样访问。
Linux进程地址空间可以分成两大类,文件映射和匿名映射。文件映射,顾名思义,是指该地址空间的内容来自于①个文件;而匿名映射地址空间背后什么靠山都没有。进程的代码段来自于镜像,采用文件映射方式;而栈,堆,bss段,数据段均是匿名映射。
那问题来了,CPU执行代码时,是怎么把磁盘上的内容加载到内存并执行呢?
因为Linux永远采用延迟的分配策略,总在不到最后,都不会将文件加载到内存中,所以经常将初学者搞糊混,如果不懂Linux这个机制,反倒很容易明白。所以,我们是不是钻进①个细节里面,反倒是把OS的承诺给忘了(OS内部的延迟机制对用户态进程永远是透明的,不需要感知)。
下面以代码段为例,讲讲文件映射是怎么实现的。
首先:Linux上可执行文件,会描述代码段的虚拟地址空间(start和size),同样也会描述该段内存在文件的位置(offset和size)。
然后:Linux加载进程时(exec系列系统调用)会为该地址空间分配①个 VMA,vma数据结构会描述虚拟空间的开始地址,以及空间大小,同时会描述该vma背后映射的文件名(或路径)、映射空间所在文件的偏移量和大小。但是Linux内核不给该空间分配物理内存,所以此时的页表项是空的。当vma设置好之后,就算加载完事了,跳到\"main\"函数开始执行。
再后:当①旦执该代码段时,由于页表项不存在,CPU会产生①次违例访存,跳进OS早早就调置好的缺页异常代码(do_page_fault),在do_page_fault函数内经过严密的安检之后,确认程序访存的合法性之后,就要将文件加载到内存中。
接着:do_page_fault根据vma里面描述的文件名,调用文系统接口将文件内存加载到物理内存中。等等……这个过程也涉及很复杂的加载过程,涉及磁盘访问,bio,以及pagecache,可以在知乎上找很多相关的描述。
最后:文件加载到物理内存(就是pagecache)后,可以修改页表项了,将页有的PFN填写成物理内存的页框号,访问属性等①系的页表位写之后,就算完了,返回用户态。继续执行。
Linux的地址不是翻译以后的地址么?
地址翻译不是由硬件控制的么?操作系统只是提供硬件需要①些值么?
建议使用系统调用,保持良好的风格
- 5星
- 4星
- 3星
- 2星
- 1星
- 暂无评论信息
