5分钟学会两年经验Linux运维都不懂的内核问题( 三 )


ok,现在我把上述测试程序改成私有匿名映射

5分钟学会两年经验Linux运维都不懂的内核问题

文章插图
 
 
这时再来看下内存的使用情况
5分钟学会两年经验Linux运维都不懂的内核问题

文章插图
 
 
我们可以看到,只有 used 增加了1G,而 buff/cache 并没有增长;说明,在进行匿名私有映射时,并没有占用 cache,其实这也是有道理,因为就只有当前进程在使用这块这块内存,没有必要占用宝贵的 cache 。
3.4 共享匿名映射
当我们需要在父子进程共享内存时,就可以用到 mmap 共享匿名映射,那么共享匿名映射的内存是存放在哪了?我继续改写上述测试程序为共享匿名映射。
5分钟学会两年经验Linux运维都不懂的内核问题

文章插图
 
 
这时来看下内存的使用情况:
5分钟学会两年经验Linux运维都不懂的内核问题

文章插图
 
 
从上述结果,我们可以看出,只有buff/cache增长了1G,即当进行共享匿名映射时,这时是从 cache 中申请内存,道理也很明显,因为父子进程共享这块内存,共享匿名映射存在于 cache,然后每个进程再映射到彼此的虚存空间,这样即可操作的是同一块内存 。
4、系统回收内存当系统内存不足时,有两种方式进行内存释放,一种是手动的方式,另一种是系统自己触发的内存回收,先来看下手动触发方式 。
4.1 手动回收内存
手动回收内存,之前也有演示过,即
echo 1 >> /proc/sys/vm/drop_caches
我们可以在 man proc 下面看到关于这个的简介
5分钟学会两年经验Linux运维都不懂的内核问题

文章插图
 
从这个介绍可以看出,当 drop_caches 文件为1时,这时将释放 pagecache 中可释放的部分(有些 cache 是不能通过这个释放的),当 drop_caches 为2时,这时将释放 dentries 和 inodes 缓存,当 drop_caches 为3时,这同时释放上述两项 。
关键还有最后一句,意思是说如果 pagecache 中有脏数据时,操作 drop_caches 是不能释放的,必须通过 sync 命令将脏数据刷新到磁盘,才能通过操作 drop_caches 释放 pagecache 。
ok,之前有提到有些pagecache是不能通过drop_caches释放的,那么除了上述提文件映射和共享匿名映射外,还有有哪些东西是存在pagecache了?
4.2 tmpfs
我们先来看下 tmpfs,tmpfs 和 procfs,sysfs 以及 ramfs 一样,都是基于内存的文件系统,tmpfs 和 ramfs 的区别就是 ramfs 的文件基于纯内存的,和 tmpfs 除了纯内存外,还会使用 swap 交换空间,以及 ramfs 可能会把内存耗尽,而 tmpfs 可以限定使用内存大小,可以用命令 df -T -h 查看系统一些文件系统,其中就有一些是 tmpfs,比较出名的是目录 /dev/shm
tmpfs 文件系统源文件在内核源码 mm/shmem.c,tmpfs实现很复杂,之前有介绍虚拟文件系统,基于 tmpfs 文件系统创建文件和其他基于磁盘的文件系统一样,也会有 inode,super_block,identry,file 等结构,区别主要是在读写上,因为读写才涉及到文件的载体是内存还是磁盘 。
而 tmpfs 文件的读函数 shmem_file_read,过程主要为通过 inode 结构找到 address_space 地址空间,其实就是磁盘文件的 pagecache,然后通过读偏移定位cache 页以及页内偏移 。
这时就可以直接从这个 pagecache 通过函数 __copy_to_user 将缓存页内数据拷贝到用户空间,当我们要读物的数据不pagecache中时,这时要判断是否在 swap 中,如果在则先将内存页 swap in,再读取 。
tmpfs 文件的写函数 shmem_file_write,过程主要为先判断要写的页是否在内存中,如果在,则直接将用户态数据通过函数__copy_from_user拷贝至内核pagecache中覆盖老数据,并标为 dirty 。
如果要写的数据不再内存中,则判断是否在swap 中,如果在,则先读取出来,用新数据覆盖老数据并标为脏,如果即不在内存也不在磁盘,则新生成一个 pagecache 存储用户数据 。
由上面分析,我们知道基于 tmpfs 的文件也是使用 cache 的,我们可以在/dev/shm上创建一个文件来检测下:
5分钟学会两年经验Linux运维都不懂的内核问题

文章插图
 
 
看到了吧,cache 增长了1G,验证了 tmpfs 的确使用的 cache 内存 。
其实 mmap 匿名映射原理也是用了 tmpfs,在 mm/mmap.c->do_mmap_pgoff 函数内部,有判断如果 file 结构为空以及为 SHARED 映射,则调用 shmem_zero_setup(vma) 函数在 tmpfs 上用新建一个文件


推荐阅读