0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux总是以Lazy的方式给应用程序分配内存

Linux阅码场 来源:未知 作者:李倩 2018-04-27 15:10 次阅读

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

1.page cache

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

read/write

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

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

mmap

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

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

使用mmap读写文件

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

编译执行:

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

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

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

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

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

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

附注:

i.swap:

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

名字:swap分区

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

2.free命令的详细解释

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

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

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

参考下图所示:

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

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

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

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

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

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

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

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

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

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

附注:

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

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

4.页面回收和LRU

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

5.swap以及zRAM

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

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

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

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    10943

    浏览量

    206546
  • 内存管理
    +关注

    关注

    0

    文章

    161

    浏览量

    14044

原文标题:郝健: Linux内存管理学习笔记-第4节课

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Linux内核内存管理之内核非连续物理内存分配

    的主要优点是避免了外部碎片,而缺点是需要修改内核页表。显然,非连续内存区域的大小必须是4096的倍数。Linux使用非连续物理内存区的场景有几种:(1)为swap区分配数据结构;(2)
    的头像 发表于 02-23 09:44 342次阅读
    <b class='flag-5'>Linux</b>内核<b class='flag-5'>内存</b>管理之内核非连续物理<b class='flag-5'>内存</b><b class='flag-5'>分配</b>

    Linux内存系统: Linux 内存分配算法

    、伙伴系统算法——组织结构1) 概念· 为内核提供了一种用于分配一组连续的页而建立的一种高效的分配策略,并有效的解决了外碎片问题· 分配内存是以
    发表于 08-24 07:44

    内核的内存是如何进行分配

    嵌入式LINUX驱动学习之12内核内存分配一、头文件、函数及说明:一、头文件、函数及说明://头文件位置 : include/linux/slab.h/*申请
    发表于 12-17 06:44

    如何通过TZASC分配安全内存并通过OP-TEE中的可信应用程序访问它?

    了 optee,然后运行了 optee_hello_world 示例,它似乎工作正常。 我现在想为安全区域分配一些内存并使用受信任的应用程序访问它。我检查了 SRM,但我需要更清楚地了解我在
    发表于 05-04 08:46

    Linux内存管理中的Slab分配机制

    早期Linux内存分配机制采用伙伴算法, 当请求分配内存大小为几十个字节或几百个字节时会产生内存
    发表于 04-24 10:49 11次下载

    嵌入式Linux NFS方式应用程序的实现

    嵌入式Linux NFS方式应用程序的实现:本文在以ARM9 内核芯片,处理器为S3C2410 构造的开发板系统上,详细讨论了如何配置嵌入式Linux NFS 开发环境,并通过一个具
    发表于 08-02 14:48 39次下载

    Linux下C应用程序开发

    本文介绍了在 Linux下能用于 C 应用程序开发和调试的工具. 本文的主旨是介绍如何在 Linux 下使用 C 编译器和其他 C 编程工具, 而非 C 语言编程的教程
    发表于 05-14 10:16 4573次阅读

    Android应用程序内存泄漏的原因及规避方法

    引言 Android应用程序内存使用的问题经常容易被忽视,在传统的编程语言中(例如C语言),回收内存的任务是由程序本身来完成的,程序可以显
    发表于 10-19 14:52 0次下载
    Android<b class='flag-5'>应用程序</b><b class='flag-5'>内存</b>泄漏的原因及规避方法

    浅谈内存分配方式 避免内存浪费问题

    说到内存分配方式,就不得不提连续分配方式。这种方式是指为一个用户程序分配一个连续的
    发表于 03-03 11:22 1251次阅读

    Linux操作系统知识讲解:走进Linux 内存分配算法

    Linux操作系统知识讲解:走进Linux 内存分配算法
    的头像 发表于 08-28 10:57 5056次阅读
    <b class='flag-5'>Linux</b>操作系统知识讲解:走进<b class='flag-5'>Linux</b> <b class='flag-5'>内存</b><b class='flag-5'>分配</b>算法

    嵌入式Linux应用程序例程

    嵌入式Linux应用程序例程(arm嵌入式开发步骤)-嵌入式Linux应用程序例程,有需要的可以参考!
    发表于 07-30 13:23 16次下载
    嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>应用程序</b>例程

    C语言堆栈程序内存分配

        程序内存分配       一个由C/C++编译的程序占用的内存分为以下几个部分: 栈区(stack)— 由编译器自动
    的头像 发表于 10-21 14:51 2086次阅读

    C语言程序编译后内存地址的分配

    (一)C程序内存分配1.内存分配图解2.内存分配介绍
    发表于 01-13 14:23 1次下载
    C语言<b class='flag-5'>程序</b>编译后<b class='flag-5'>内存</b>地址的<b class='flag-5'>分配</b>

    Linux内核之块分配

    为了解决小块内存分配问题,Linux 内核提供了块分配器,最早实现的块分配器是SLAB 分配
    的头像 发表于 07-27 09:35 1200次阅读

    Linux内核引导内存分配器的原理

    Linux内核引导内存分配器使用的是伙伴系统算法。这种算法是一种用于动态内存分配的高效算法,它将内存
    发表于 04-03 14:52 227次阅读