内存管理四

         发了前几天的总结后,有群里的朋友@jeff表示,我这样大篇幅的文字描述,估计没几个人有耐心看下去,想想也是,内存管理本身就比较复杂,枯燥。所以这一次尽量使用图片进行说明,然后逐步展开。话不多说,先上图吧。


如图所示:有两条脉络,分别用黄线和蓝线标识,黄线的脉络为有文件背景的数据交换过程,蓝线为无文件背景的数据交换过程,红色为有文件背景的节点,绿色为无文件背景的节点。

         那么何为有文件背景的页File-backedpage,何为无文件背景的页,也就是匿名页anonymous page,直接盗用宋老师课件图片:


特别说明一下程序的代码段,程序运行的时候,实际上是把ELF文件的代码段加载到物理内存的page cache,然后映射到内核空间的page cache页,所以程序的代码段也是file backed的。

         接下来分两条脉络来进行说明和扩展。

 

Filebacked

         在硬盘中能对应到实际的文件的,归纳为file backed,文件在open后,会被加载到物理内存,我们称这片内存为page cache页,在3.14版本以前的内核,page cache又被划分为buffers和cache,3.14版本以后不做区分,全部看作page cache。Page cache被映射到内核空间的虚拟地址,用户通过两种方式访问磁盘上的文件,直接读写和mmap到用户空间,可能触发page cache页面和磁盘数据交换的有LRU,手动同步SYNC和内存回收reclaim。

         上面的一段话,描述了filebacked的整体脉络,有一下几个问题需要单独说明:

A.3.14版本以前的pagecache划分为buffers和cache,他们有什么区别?

要说明这个问题,先明确一个概念,pagecache作为磁盘的一个缓冲,它缓冲过来的文件内容是可以被牺牲掉的,就是说我内存空间不足的时候,我可以回收这部分内存资源,所以在Linux操作系统看来,这部分内存虽然被占用,但是仍然是available的。


         通过free命令,可以看到3.13版本分别列出了buffers和cached的数值,buffers值是直接操作裸分区的pagecache的大小,比如我们通过dd命令读写SD卡;cached值是操作文件系统上的文件的page cache的大小,比如直接open dev/sda1/hello.c文件,这个文件的page cache被叫做cached。

看上图,free命令的第三行,有一个-/+buffers/cache,这个值是如何计算的呢?

上面说过,page cache是可牺牲的,这个值就是page cache被回收后的内存的used和free的值,盗用宋老师课件again。


其实这种划分没有什么特别的意义,他们的区别是各自的background不同而已,所以3.14版本之后的内核不做buffers和cached的区分,free命令的-/+ buffers/cache这一行也不再需要,只是单独搞出一个available值,用于表示当前系统中包括已经使用的page cache(可牺牲),到底有多少可利用的内存。


原谅我的free还不够给力,并没有列出available值。

        

B.mmap和直接读写有什么区别?

         Pagecache被映射到内核空间后,用户想要操作对应的文件,实际上是对内存里page cache的操作,系统会在合适的时机回写到磁盘中对应的文件。操作的方式有两种,直接读写,和通过mmap把page cache在映射到用户空间一份。

         程序调用read、write函数的时候,陷入到内核空间,实际调用的是file operation结构的read、write接口,这两个接口必然要做的一件事就是copy_from_user和copy_to_user,我们知道这两个函数是会引起内核空间与用户空间的数据拷贝的,就是说每一次read和write都要进行一次拷贝。

         mmap则完全不同,它把pagecache直接映射到用户空间,现在用户空间和内核空间的页表都可以对应到page cache物理内存。然后通过mmap返回的指针来读写page cache,这个过程是没有用户空间和内核空间的内存拷贝的。

         通常在操作显存设备的时候会使用mmap,比如我可以通过mmap把/dev/fb0映射到用户空间,通过读写mmap返回的指针来实现对屏幕的显示。

 

C.LRU是个什么鬼?

         LUR,LeastRecently Used,翻译过来就是最近最少使用,顾名思义,内核把最近最少使用的page cache内容或者anonymous页面交换出去。上图,盗图three


现在cache的大小是4页,前四次,1,2,3,4文件被一次使用,注意第七次,5文件被使用,系统评估最近最少被使用的文件是3,那么不好意思,3被swap出去,5加载进来,依次类推。

         所以LRU可能会触发pagecache或者anonymous页与对应文件的数据交换。

 

D.SYNC指的什么,如何触发pagecache与文件的数据交换?

         系统为用户提供了,数据从pagecache回写到文件的接口,sync命令。只要运行sync命令就可以触发page cache与文件的数据交换。

         另外,我们还可以通过向/proc/sys/vm/drop_caches写入数字来清空对应的caches,一般写入之前,最好执行一下sync命令来同步一下,以便释放更多的空间,因为drop_caches只回收clean pages,不回收dirty pages,所以如果想回收更多的cache,应该在drop_caches之前先执行"sync"命令,把dirty pages变成clean pages。

echo 1 > /proc/sys/vm/drop_caches   //清空 pagecache

echo 2 > /proc/sys/vm/drop_caches   //清空 dentries 和 inodes

echo 3 > /proc/sys/vm/drop_caches   //清空所有缓存(pagecache、dentries 和 inodes)

 此处附上一个说明链接:http://mp.weixin.qq.com/s/_uzF82DYhvs69-I9R6dtMw


anonymous

         在进程中定义的堆,栈等没有文件背景的页面,如果系统没有创建swap分区或者swap文件,那不好意思,匿名页只能常驻内存,直到程序退出,或者发生OOM程序被干掉。与file backed不同的是,anonymous本身就在内存中,而file backed是磁盘中的文件,为了提高效率把内存作为磁盘的缓冲区,就是page cache,page cache可以往对应文件交换,anonymous页如果过大的话,可以往swap分区或者创建的swap文件中交换。要操作这些匿名页,直接在程序源码中操作变量和动态分配内存的指针就好了。

         那么,对于anonymous页,在什么情况下会触发数据交换呢?

除了LRU会产生匿名页的交换,内存回收也会引发数据交换,reclaim,Linux有一个后台进程kswapd,负责回收page cache和匿名页,回收速度较慢,但是不会影响程序运行,程序不会被delay,当系统内存资源异常紧张时,会触发Direct reclaim,这个过程回收速度较快,但是进程会被直接delay,直到回收够足够的内存。

         至于何时kswapd开始回收内存,何时Directreclaim,有三个门限值,min,low,hight,当内存的水位达到low,说明内存紧张,这时kswapd开始工作,慢慢回收内存,直到水位达到high,当系统内存异常紧张时,达到min水位,Direct reclaim被触发。

 

Swappiness

         当系统内存不足时,可以从filebacked pages或者anonymous pages回收内存,不论哪个被回收,再次被加载进内存一定都会影响程序的效率。具体从哪里回收,Linux提供swappiness值作为衡量标准。

         Swappiness越大,越倾向于回收匿名页;swappiness越小,越倾向于回收file-backed的页面。当然,它们的回收方法都是一样的LRU算法。盗图four。


顺便附上一个参考链接:http://mp.weixin.qq.com/s/BixMISiPz3sR9FDNfVSJ6w

 

zRamswap

         对于嵌入式设备,它的磁盘是SD卡,MMC,一方面速度较慢,另一方面,有使用寿命的问题,不太适合做swap分区。嵌入式设备一般会从内存中拿出一小部分当作虚拟内存,这个就是zRam。但是这样直接用又没有什么意义,因为虚拟内存的目的就是在内存不足时“扩展内存”,现在内存还是那片内存,就是换了个说法,所以为了“扩展内存”,当系统把内存交换到这个虚拟内存,通常是以压缩的方式存储,当swap in时在解压。这样就某种程度的“扩展了内存”,但是缺点是增加了CPU的压力,需要进行压缩和解压缩。

 所以zRam一般用在小内存的设备上,且存在频繁切换任务的情况,zRam可提高用户体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值