一步一图带你深入理解 Linux 虚拟内存管理( 十 )


设置这个值即为 mmap 的共享映射,不设置的话则为私有映射 。这个等后面我们讲到 mmap 的相关实现时还会再次提起 。
VM_IO 的设置表示这块虚拟内存区域可以映射至设备 IO 空间中 。通常在设备驱动程序执行 mmap 进行 IO 空间映射时才会被设置 。
VM_RESERVED 的设置表示在内存紧张的时候 , 这块虚拟内存区域非常重要 , 不能被换出到磁盘中 。
VM_SEQ_READ 的设置用来暗示内核 , 应用程序对这块虚拟内存区域的读取是会采用顺序读的方式进行 , 内核会根据实际情况决定预读后续的内存页数,以便加快下次顺序访问速度 。
VM_RAND_READ 的设置会暗示内核,应用程序会对这块虚拟内存区域进行随机读?。诤嗽蚧岣菔导是榭黾跎僭ざ恋哪诖嬉呈踔镣V乖ざ?。
我们可以通过 posix_fadvise,madvise 系统调用来暗示内核是否对相关内存区域进行顺序读取或者随机读取 。相关的详细内容,大家可以看下笔者上篇文章 《从 Linux 内核角度探秘 JDK NIO 文件读写本质》中的第 9 小节文件页预读部分 。
通过这一系列的介绍 , 我们可以看到 vm_flags 就是定义整个虚拟内存区域的访问权限以及行为规范 , 而内存区域中内存的最小单位为页(4K),虚拟内存区域中包含了很多这样的虚拟页,对于虚拟内存区域 VMA 设置的访问权限也会全部复制到区域中包含的内存页中 。
5.5 关联内存映射中的映射关系接下来的三个属性 anon_vma,vm_file,vm_pgoff 分别和虚拟内存映射相关,虚拟内存区域可以映射到物理内存上,也可以映射到文件中 , 映射到物理内存上我们称之为匿名映射,映射到文件中我们称之为文件映射 。
那么这个映射关系在内核中该如何表示呢?这就用到了 vm_area_struct 结构体中的上述三个属性 。
一步一图带你深入理解 Linux 虚拟内存管理

文章插图
当我们调用 malloc 申请内存时,如果申请的是小块内存(低于 128K)则会使用 do_brk() 系统调用通过调整堆中的 brk 指针大小来增加或者回收堆内存 。
如果申请的是比较大块的内存(超过 128K)时,则会调用 mmap 在上图虚拟内存空间中的文件映射与匿名映射区创建出一块 VMA 内存区域(这里是匿名映射) 。这块匿名映射区域就用 struct anon_vma 结构表示 。
当调用 mmap 进行文件映射时,vm_file 属性就用来关联被映射的文件 。这样一来虚拟内存区域就与映射文件关联了起来 。vm_pgoff 则表示映射进虚拟内存中的文件内容,在文件中的偏移 。
当然在匿名映射中,vm_area_struct 结构中的 vm_file 就为 null,vm_pgoff 也就没有了意义 。
vm_private_data 则用于存储 VMA 中的私有数据 。具体的存储内容和内存映射的类型有关,我们暂不展开论述 。
5.6 针对虚拟内存区域的相关操作struct vm_area_struct 结构中还有一个 vm_ops 用来指向针对虚拟内存区域 VMA 的相关操作的函数指针 。
struct vm_operations_struct { void (*open)(struct vm_area_struct * area); void (*close)(struct vm_area_struct * area);vm_fault_t (*fault)(struct vm_fault *vmf);vm_fault_t (*page_mkwrite)(struct vm_fault *vmf);..... 省略 .......}
  • 当指定的虚拟内存区域被加入到进程虚拟内存空间中时,open 函数会被调用
  • 当虚拟内存区域 VMA 从进程虚拟内存空间中被删除时,close 函数会被调用
  • 当进程访问虚拟内存时,访问的页面不在物理内存中,可能是未分配物理内存也可能是被置换到磁盘中,这时就会产生缺页异常,fault 函数就会被调用 。
  • 当一个只读的页面将要变为可写时 , page_mkwrite 函数会被调用 。
struct vm_operations_struct 结构中定义的都是对虚拟内存区域 VMA 的相关操作函数指针 。
内核中这种类似的用法其实有很多,在内核中每个特定领域的描述符都会定义相关的操作 。比如在前边的文章 《从 Linux 内核角度探秘 JDK NIO 文件读写本质》 中我们介绍到内核中的文件描述符 struct file 中定义的 struct file_operations*f_op 。里面定义了内核针对文件操作的函数指针,具体的实现根据不同的文件类型有所不同 。
针对 Socket 文件类型,这里的 file_operations 指向的是 socket_file_ops 。
一步一图带你深入理解 Linux 虚拟内存管理

文章插图
在 ext4 文件系统中管理的文件对应的 file_operations 指向 ext4_file_operations,专门用于操作 ext4 文件系统中的文件 。还有针对 page cache 页高速缓存相关操作定义的 address_space_operations。

推荐阅读