都说透彻理解Linux内存管理非常困难!总结Linux内存管理知识!
奔跑吧Linux社区 2023-06-09
Linux的内存管理涉及到的内容非常庞杂,而且与内核的方方面面耦合在一起,想要理解透彻非常困难。

在开始学习之前进行了一些准备工作《如何展开Linux Memory Management学习?》,

1. 参考资料

遂决定以如下资料作为参考,进行Linux内存管理的研究:

《奔跑吧 Linux内核》:以第2章为蓝本展开,这是目前能获取的紧跟当前内核发展(Linux 4.0),并且讲的比较全面的一本资料。

《Understanding the Linux Virtual Memory Manager》:简单说就是虽老但经典,基于(Linux 2.4/2.6)。作者是目前仍然活跃在Linux社区MM专家。

《wowotech Memory Management》:没有其他系列经典,也没有条理系列的介绍MM,但是仍然值得按考。

《tolimit Linux内存源码分析》:相对零散的介绍了内存相关分析文档

《Linux Kernel v4.0》:当然必不可少的,是源码了。

当逐渐深入看到MMU相关代码时,读一下ARM架构关于MMU的规格书有助于理解。

不然对于虚拟地址到物理地址的映射就会很虚无,这些资料包括《ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition》的《Virtual Memory System Architecture》,以及相关MMU TRM。

2. Linux Memory Management框架图

整个内存管理从宏观上可以分为三大部分:用户空间、内核空间和相关硬件。

用户空间主要是libc对相关系统调用进行封装,对用户程序提供API,常用的有malloc、mmap、munmap、remap、madvise、mempolicy等等。

相关硬件包括MMU/TLB、L1/L2 Cache以及DDR RAM,具体到ARM架构需要对照MMU/L2 Cache以及RAM规格书。

内核空间就复杂多了,首先介绍初始化及初始化后的布局。

2.1物理内存初始化从获取内存大小、初始化页表,再进行zone初始化,然后在zone中使用伙伴系统进行物理内存初始化;

2.2页表的映射过程讲述了ARM32和ARM64两种架构下的页表映射,如何从虚拟地址由MMU转化成物理页面地址的;

2.3内核内存的布局图在内存被初始化之后,内核的内存布局基本上就确定了,ARM32和ARM64下布局有很大区别。在malloc一节brk中介绍了用户空间的布局。
2.1~2.3是内存的一个静态状态,在有了这些基础之后,2.4~2.9按照从低层到上层的逐个介绍了。
2.4分配物理页面介绍了基于伙伴系统的页分配和释放;
2.5slab分配器基于伙伴系统,slab分配更小内存块;以及基于slab的kmalloc;
2.6vmalloc和kmalloc区别在于v,即在VMALLOC区域分配;
2.7VMA即Virtual Memory Area,是进程内存管理的核心;
2.8malloc和2.9mmap都基于VMA,malloc/free用于分配/释放一块内存;mmap/munmap用于匿名/文件映射到用户空间。以及mmap(补充)。
由于malloc/mmap分配内存并不是立即分配,只是在用到的时候才会触发2.10缺页中断处理。
在缺页但页不足的情况下,就需要进行一些操作调整内存,这些操作的基础是2.11page引用计数,还有页面的2.12反向映射RMAP技术。
在内存不足情况下触发kswapd2.13 回收页面,其中匿名页面有着特殊的2.14匿名页面生命周期。
在kswapd回收依然无法满足内存分配,就需要对内存进行2.16内存规整,它依赖的技术是2.15页面迁移。
由于内存中存在一些内容完全一样的页面,使用2.17KSM技术进行合并,同时利用COW技术,在需要时重新分配。
还介绍了2.18Dirty COW内存漏洞,然后对内存管理数据结构和API进行了总结2.19总结内存管理数据结构和API。
最后2.20最新更新和展望对新技术进行了介绍。
除了以上技术,还有如下内存技术:

  1. swap计数把匿名页面写入SWAP分区从而释放出空闲页面

  2. 内存压缩技术zram(a compressed RAM based swap device)

  3. zswap技术是zram和swap的一个综合,首先将待换出页面进行压缩,存储到系统RAM动态分配的内存池中;达到一定阈值后再写入实际交换设备。

  4. 在内存极端不足情况下使用21 OOM(Out-Of-Memory)来杀死不重要进程获取更多内存的技术

  5. 基于cgroup的Memory资源控制

  6. 解决多媒体对大量连续内存需求的CMA(Contiguous Memory Allocator)技术

  7. slub分配器

  8. memory hotplug内存热插拔支持动态更换内存物理设备

在对内存相关技术了解过后,就是如何运用的问题了?
一方面是对内存问题进行定位;另一方面是对内存行为施加影响,进行优化。
22内存检测技术对Linux内存常见问题及其定位方法和工具(slub_debug/kmemleak/kasan)进行了讲解。
23一个内存Oops解析以一个内存Oops为例,介绍了内存相关异常分析。
内存sysfs节点和工具介绍了linux内存管理相关sysfs节点,以及工具;借助这些可以对内存进行优化。
扩展阅读:
关于zram、zswap、zcache的区别与各自优缺点《zram vs zswap vs zcache Ultimate guide: when to use which one》

Linux内存管理框架图

3. 代码和测试环境搭建

3.1 QEMU
安装QEMU以及相关编译工具

sudo apt-get install qemu libncurses5-dev gcc-arm-linux-gnueabi build-essential

3.2 Busybox 1.24
下载Busybox 1.24代码:

git clone https://github.com/arnoldlu/busybox.git -b 1_24_stable 

编译Busybox:

export ARCH=arm export CROSS_COMPILE=arm-linux-gnueabi- #make menuconfig #P684,进行配置 make -j4 install

配置initramfs:

sudo cp -r running_kernel_initramfs/* _install/
sudo chmod +x _install/etc/init.d/rcS
cd _install mkdir mnt mkdir dev
cd dev
sudo mknod console c 5 1 sudo mknod null c 1 3 

3.3 Kernel 4.0
下载Linux Kernel 4.0代码:

git clone https://github.com/arnoldlu/linux.git -b running_kernel_4.0 

编译Linux Kernel:

export ARCH=arm export CROSS_COMPILE=arm-linux-gnueabi-
make vexpress_defconfig #P685进行配置 make bzImage -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
make dtbs

3.4 运行内核

#Run Kernel+Busybox in QEMU qemu-system-arm -M vexpress-a9 -smp 4 -m 1024M -kernel arch/arm/boot/zImage -append "rdinit=/linuxrc console=ttyAMA0 loglevel=8" -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic

至此,已经有一个完整的环境,提供shell命令。

4. 思考问答

  1. 在系统启动时,ARM Linux内核如何知道系统中有多大的内存空间?

  2. 在32bit Linux内核中,用户空间和内核空间的比例通常是3:1,可以修改成2:2吗?

  3. 物理内存页面如何添加到伙伴系统中,是一页一页添加,还是以2的几次幂来加入呢?

  4. 内核的一级页表存放在什么地方?二级页表又存放在什么地方?

  5. 用户进程的一级页表存放在什么地方?二级页表呢?

  6. 在ARM32系统中,页表是如何映射的?在ARM64系统中,页表又是如何映射的?

  7. 请简述Linux内核在理想情况下页面分配器(page allocator)是如何分配出连续物理页面的。

  8. 在页面分配器中,如何从分配掩码(gfp_mask)中确定可以从哪些zone中分配内存?

  9. 页面分配器是按照什么方向来扫描zone的?

  10. 为用户进程分配物理内存,分配掩码应该选用GFP_KERNEL,还是GFP_HIGHUSER_MOVABLE呢?

  11. slab分配器是如何分配和释放小块内存的?

  12. slab分配器中有一个着色的概念(cache color),着色有什么作用?

  13. slab分配其中的slab对象有没有根据Per-CPU做一些优化?

  14. slab增长并导致大量不用的空闲对象,该如何解决?

  15. 请问kmalloc、vmalloc和malloc之间有什么区别以及实现上的差异?

  16. 使用用户态的API函数malloc()分配内存时,会马上为其分配物理内存吗?

  17. 假设不考虑libc的因素,malloc分配100Byte,那么实际上内核是为其分配100Byte吗?

  18. 假设两个用户进程打印的malloc()分配的虚拟地址是一样的,那么在内核中这两块虚拟内存是否打架了呢?

  19. vm_normal_page()函数返回的是什么样页面的struct page数据结构?为什么内存管理代码中需要这个函数?

  20. 请简述get_user_page()函数的作用和实现流程?

  21. 请简述follow_page()函数的作用和实现流程?

  22. 请简述私有映射和共享映射的区别。

  23. 为什么第二次调用mmap时,Linux内核没有捕捉到地址重叠并返回失败呢?

  24. struct page数据结构中的_count和_mapcount有什么区别?

  25. 匿名页面和page cache页面有什么区别?

  26. struct page数据结构中有一个锁,请问trylock_page()和lock_page()有什么区别?

  27. 在Linux 2.4.x内核中,如何从一个page找到所有映射该页面的VMA?反响映射可以带来哪些便利?

  28. 阅读Linux 4.0内核RMAP机制的代码,画出父子进程之间VMA、AVC、anon_vma和page等数据结构之间的关系图。

  29. 在Linux 2.6.34中,RMAP机制采用了新的实现,在Linux 2.6.33和之前的版本中称为旧版本RMAP机制。那么在旧版本RMAP机制中,如果父进程有1000个子进程,每个子进程都有一个VMA,这个VMA里面有1000个匿名页面,当所有的子进程的VMA同时发生写复制时会是什么情况呢?
    当page加入lru链表中,被其他线程释放了这个page,那么lru链表如何知道这个page已经被释放了。

  30. kswapd内核线程何时会被唤醒?

  31. LRU链表如何知道page的活动频繁程度?

  32. kswapd按照什么原则来换出页面?

  33. kswapd按照什么方向来扫描zone?

  34. kswapd以什么标准来退出扫描LRU?

  35. 手持设备例如Android系统,没有swap分区或者swap文件,kswapd会扫描匿名页面LRU吗?

  36. swappiness的含义是什么?kswapd如何计算匿名页面和page cache之间的扫描比重?

  37. 当系统充斥着大量只访问一次的文件访问(use-one streaming IO)时,kswapd如何来规避这种风暴?

  38. 在回收page cache时,对于dirty的page cache,kswapd会马上回写吗?

  39. 内核有哪些页面会被kswapd写回交换分区?

  40. ARM32 Linux如何模拟这个Linux版本的L_PTE_YOUNG比特位呢?

  41. 如何理解Refault Distance算法?

  42. 请简述匿名页面的生命周期。在什么情况下会产生匿名页面?在什么条件下会释放匿名页面?

  43. KSM是基于什么原理来合并页面的?

  44. 在KSM机制里,合并过程中把page设置成写保护的函数write_protect_page()有这样一个判断:这个判断的依据是什么?

  45. 如果多个VMA的虚拟页面同时映射了同一个匿名页面,那么此时page->index应该等于多少?

  46. 为什么Dirty COW小程序可以修改一个只读文件的内容?

  47. 在Dirty COW内存漏洞中,如果Diryt COW程序没有madviseThread线程,即只有procselfmemThread线程,能否修改foo文件的内容呢?

  48. 假设在内核空间获取了某个文件对应的page cache页面的struct page数据结构,而对应的VMA属性是只读,那么内核空间是否可以成功修改该文件呢?

  49. 如果用户进程使用只读属性(PROT_READ)来mmap映射一个文件到用户空间,然后使用memcpy来写这段内存空间,会是什么样的情况?

  50. 请画出内存管理中常用的数据结构的关系图,如mm_struct、vma、vaddr、page、pfn、pte、zone、paddr和pg_data等,并思考如下转换关系。

  51. 请画出在最糟糕的情况下分配若干个连续物理页面的流程图。

  52. 在Android中新添加了LMK(Low Memory Killer),请描述LMK和OOM Killer之间的关系。

  53. 请描述一致性DMA映射dma_alloc_coherent()函数在AEM中是如何管理cache一致性的?

  54. 请描述流式DMA映射dma_map_single()函数在ARM中是如何管理cache一致性的?

  55. 为什么在Linux 4.8内核中要把基于zone的LRU链表机制迁移到基于Node呢?


本文源自微信公众号:奔跑吧Linux社区,不代表用户或本站观点,如有侵权,请联系nick.zong@aspencore.com 删除!

声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
  • 相关技术文库
  • 硬件
  • 原理图
  • 信号完整性
  • EMI
  • 应用BK5822设计ETC OBU

      中国的公路不停车收费(ETC)系统应用市场越来越大,为了促进ETC应用的快速发展和成熟,国家相关部门开展了高速公路联网不停车收费的试点工程,比如,京津翼地区和长三角地区,所以对车载单元(OBU)的需求量也随之大幅增加。  目前市场上应用的OBU多数是通过分立元器件设计实现的,存在一致性、稳定性和可靠性的问题。博通(BEKEN)集成电路于2010年年初推出用于ETC系统的射频收发器">射频...

    09-28
  • 一种单芯片GPS接收机的硬件设计

    引言   GPS(全球定位系统)发展到今天,其用途越来越广泛,而技术的进步和用户需求也不断推动GPS系统的增强。目前美国正在致力于GPSBlockII系统的现代化和“GPS - III”计划,旨在全面改善GPS的生命力、精度、可用性、完好性、灵活性和安全性。  GPS用户端设备也处于不断升级和发展之中。从接收机的结构来看,随着VLSI(超大规模集成电路)和DSP技术的发展,单通道序贯式、时分多路复...

    09-28
  • 半刚性电缆是指什么

    半刚性电缆组件的最基本形式为由金属管构成的同轴传输线。其中,所述金属管一般为形成外导体的铜管,沿该铜管的中心线设有金属丝导体。所述中心金属丝导体由介电材料支撑...

    09-27
  • 比Wi-Fi快100倍的网络 真的靠谱吗?

    Wi-Fi 对移动计算的使用产生了巨大的影响,使员工可以在任何地方访问公司网络,咖啡店也能成为独立工作人员的办公地点。但Wi-Fi 也有其缺点,所以诞生了一个新的标准:Li-Fi,如果它可以顺利上市,

    09-26
  • 产品设计共用一款PCB一套软件,如何区分判断?

    在实际的工程项目中,有时候会碰到两款差异不大的产品,设计的时候共用一款PCB,软件也共用一套软件。这个时候,我们可以开辟一个IO口,用于侦测实际应用的是哪款产品

    09-25
  • 探究CDMA网络在MBB时代的发展趋势和应对策略,推动移动通信技术创新

    面对日新月异的移动终端和爆炸式增长的移动应用,移动互联网流量未来10年将迎来数百倍的增长。MBB洪流已然来袭,然而,它们主要来自哪里?

    09-25
  • 数字功放与模拟功放的优缺点对比:深入分析两种功放技术的特点与应用,助您选择适合的音频放大方案

     “数字功放”的基本电路是早已存在的D类放大器(国内称丁类放大器)。以前,由于价格和技术上的原因,这种放大电路只是在实验室或高价位的测试仪器中应用。这几年的技术发展使数字功放的元件集成到一两块芯片中,

    09-25
  • 基于触控屏的无线通信噪声干扰验证研究

    本文所探讨的内容虽然仅是噪声验证的其中一个例子,但我们已可以见微知着的了解到,无线通讯讯号技术的博大精深,以及干扰掌控的技术深度。所有相关厂商业者在开发时,均需透过更深入的研究、更多的技术资源与精力投

    09-25
  • 深入探讨两种常见的比例放大电路设计方案,实现精确信号放大功能

    运算放大器,它有两个输入引脚和一个输出引脚。其中两个输入引脚,一个是正相输入,一个是负相输入。正是因为运算放

    09-25
  • 优化光缆路由:降低光网络时延的关键因素分析与解决方案研究

    中国电信日前发布了《低时延光网络白皮书》,指出了四大需求低时延的业务。第一是金融和电子交易类用户;第二是基于TCP协议的高清视频类业务,包括4K/8K、视频会议、VR等实时性要求极高的大带宽业务;第三

    09-25
  • 浅析915MHz发射/接收模块电路设计

    设计为868MHz和902至928MHz 的AMR解决方案,RFMD的RF6549功能独立的Rx和Tx路径,两个连接多样性的解决方案或一个测试端口的输出端口的端口。PA的部分包括一个标称输出功率为28

    09-25
下载排行榜
更多
评测报告
更多
广告