【推荐阅读】
0x00内存页面分类与换入换出规则
内存页面分为用户页面和内核页面。
用户页面有以下几种:
1、普通的用户空间页面,包括进程的代码段、数据段、堆栈段、以及动态分配的存储堆。
2、通过系统调用mmap()映射到用户空间的已打开文件的内容。
这些页面既涉及分配、使用和回收,也涉及页面的换出/换入。
内核页面有以下几种:
1、kmalloc分配用作某些临时性的数据结构,如vma_area_struct。
2、内核通过alloc_page分配,如每个进程的系统堆栈所在的两个页面。
这些页面不涉及页面的换出/换入,一旦使用完毕,就可以释放、回收。
3、文件系统相关的结构体如dentry、node
这些页面不涉及页面的换出/换入,但即使使用完毕,其内容仍有保存的价值,只要条件允许,就将这些页面养起来,可以提高以后的操作效率
4、内核代码和内核中全局量所占的内存页面
这些页面既不需要分配,也不会被释放
0x01用户页面的换入
对于内核来说,只有两种用户页面,一种是文件映射,一种是匿名映射。前一种和swap没有关系,直接换出到硬盘上文件。后者会交换到swap。
1、文件映射--->换出到硬盘
2、匿名映射--->换出到swap
既然涉及到换出,我们还是先说下换入,换入也由换出定义的这两种页面为导向。
1、可执行文件(文件映射还包含直接映射硬盘上某个文件,不限于可执行文件)的换入
error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
elf_prot, elf_flags, 0);
elf_map会进一步调用mmap将可执行文件的映射到内存,这种映射属于文件映射。
我们先看下映射到内存虚拟地址的情况:
0x00601000-0x00602000这个虚拟地址空间映射为可写,我们再来看看这个区域到底放着什么信息?
里面是.data段、.bss段一些可写的段。
那么就涉及到一个问题,既然是文件映射,当发生页面短缺时,是要换出到硬盘的。我们可以想象下总不可能每执行一次文件,我硬盘的可执行文件的数据就变化一下吧?那么linux内核是怎么处理的呢?我们放在后面再说。
首先理清一个思路,mmap这个系统调用,只是申请一片虚拟内存地址,并没有实际到把硬盘中的数据读到内存,并建立映射(建立页目录表、页表)。
当访问到对应的虚拟地址空间时,触发缺页中断do_no_page,从硬盘中把数据读到内存,并建立映射。
if (!pte_present(entry)) {//页面不在内存中