linux系统分配文件夹内存,Linux总是以Lazy的方式给应用程序分配内存

Linux总是以Lazy的方式给应用程序分配内存,包括堆、栈(函数调用越深,用的栈越多,最终发生page fault才得到栈)、代码段、数据段。那么,这些已经获得到内存的段会一直占用着内存吗?

1.page cache

b1a1e612b2db5b6a21c5ee975cebd744.png

Linux下读写文件,主要有两种方式:

read/write

调用read读文件,Linux内核会申请一个page cache,然后把文件读到page cache中,再将内核空间的page cache拷贝到用户空间的buf。

调用write写文件,则将用户空间buf拷贝到内核空间page cache。

mmap

mmap可以避免buf从用户空间到内核空间的拷贝过程。

直接把文件映射成一个虚拟地址指针,这个指针指向内核申请的page cache。内核知道page cache与硬盘中文件的对应关系。

使用mmap读写文件

b8a32d298a4574b0d2f2f66e50d4ef7e.png

注:读写权限需要对应,否则触发page fault。

编译执行:

e277d36c2a1cf0b66083e71a7798b2a3.png

mmap看起来是由一个虚拟地址对应一个文件(可以直接用指针访问文件),本质上是把进程的虚拟地址空间映射到DRAM(内核从这片区域申请内存做page cache),而这个page cache对应磁盘中的某个文件,且Linux内核会维护page cache和磁盘中文件的交换关系。详见下图:

34b8f097e7a601060133c50315d17a08.png

page cache可以看作内存针对磁盘的一个缓存,应用程序在写文件时,其实只是将内容写入了page cache,使用sync才能真的写入文件。

ELF可执行程序头部会记录代码段的位置,代码段的本质就将ELF文件中的代码段直接mmap映射到一个虚拟地址,且权限为R+X。

page cache可以极大的提高系统整体性能。如,进程A读一个文件,内核空间会申请page cache与此文件对应,并记录对应关系,进程B再次读同样的文件就会直接命中上一次的page cache,读写速度显著提升。但注意,page cache会根据LRU算法(最近最少使用)进行替换。

演示:page cache对程序执行时间的影响

c434d423263821f5d7346e973e292d60.png

第一次多出很多硬盘io操作;第二次python的很多环境都在内存中命中了,速度提升显著。用\time -v命令再次对比:

144e5ca2a8dd906dc657f46190efda00.png

附注:

i.swap:

动词:swapping,内存与磁盘的颠簸行为

名字:swap分区

ii.cache可以通过/proc/sys/vm/drop_caches强行释放,写1释放page cache,2释放dentries和inode,3释放两者。

2.free命令的详细解释

38f4bd1a727f76b6451d0cc3b69f95e6.png

上图中,buffers与cached都是文件系统的缓存,没有本质区别,唯一区别是背景不同:

i.当以文件系统(ext4,xfs等)的形式去访问文件系统中的文件,如mount /dev/sda1 /mnt后,/mnt目录下会有很多文件,访问这类文件所产生的cache就对应free命令显示的cached列。

ii.直接访问/dev/sda1时,如用户程序直接打开open(“dev/sda1…)或执行dd命令,以及文件系统本身去访问裸分区,所产生的cache对应free命令显示的buffers列。

参考下图所示:

9ef1f0b25a3a7605abd4abe321bb43eb.png

演示:读硬盘裸分区导致free命令显示内容变化

3b26369062b0900eb78ab12e7248a5cd.png

linux kernel 3.14版本以后,已经采用新的free命令,如下图:

bf5eb5dd4ca2af0ce25df23a5a6bc5a8.png

老版本free中-/+buffers/cache的含义如下图:

87937c8094bf0ebf1658729e7d6fa734.png

新版本free中多出available,即是评估出现在还有多少内存可供应用程序使用。

3.file-backed的页面和匿名页

f90daeae0d9cf755f448c9c2f75b9ee7.png

page cache和CPU内部cache一样,是可以被替换出去的。有文件背景的页面可以swap到磁盘。EG. 启动firefox,跑一个oom的程序,前后对比firefox的smaps文件。可以看出firefox在内存紧张的情况下,代码段、mmap的字体文件等都被替换出去而不驻留内存了。

那么,没有文件背景的匿名页是如何交换回收的呢?是否常住内存?详见下图:

4a312dcf2ade6115b23e454c497518c8.png

有文件背景的页面和匿名页都需要swap,有文件背景的页面向自己的文件背景中交换,匿名页向swap分区和swapfile中交换。即使编译内核时将CONFIG_SWAP关闭(只是关闭了匿名页的交换),linux内核中kswapd的线程还是会swap有文件背景的页面。

5e3495ea333b1032c58fa1ed14c3cb96.png

Linux有三个水位:min,low,high。一旦内存达到低水位时,后台自动回收直到回收到高水位。当内存到达min水位时,直接堵住进程进行回收。

匿名页和有文件背景的页面都有可能被回收,/proc/sys/vm/swappiness值比较大时,倾向回收匿名页;swappiness值比较小时倾向回收有文件背景的页面。回收算法皆为LRU。

附注:

数据段比较特殊,在没有写的情况是有文件背景的,但被写后就变为匿名页。

Windows中的虚拟内存就相当于Linux的swapfile。

4.页面回收和LRU

495c0e068892118504148ec59a72175b.png

如上图,运行到第4列时,第1页最不活跃。运行到第5列时又把第1页踏了一次,此时第2页变为最不活跃的。运行到第6列时又把第2页踏了一次,此时第3页变为最不活跃的,所以在第7列时,由于要访问一个新的第5页,3就被替换出去。

5.swap以及zRAM

嵌入式系统受flash限制,很少使用swap分区,一般都swapoff。所以嵌入式系统引入zRAM技术。

23fac0de6dcb7cd6841a3b31783bf8ec.png

zRAM直接把一块内存模拟成一个硬盘分区,当作swap分区使用,此分区自带透明压缩功能,当匿名页向zRAM分区写时,Linux内核使CPU自动对匿名页进行压缩。接下来,当应用程序又执行到刚才的匿名页时,由于此页已经被swap到zRAM中,内存中没有命中,页表也没有命中,所以此时再去访问这块内存时再次发生page fault,Linux就从zRAM分区中将匿名页透明的解压出来还到内存中。

zRAM的特点是用内存来做swap分区,透明压(两页匿名页有可能被压缩成一页),透明解(一页解压成两页),这样其实相当于扩大了内存,但会多损耗一些CPU。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值