关于内存管理:Linux内核内存管理总结

微信公众号:奔跑吧linux社区

加奔跑吧微信群请先加微信:runninglinuxkernel
欢送订阅奔跑吧配套旗舰篇视频节目:https://weidian.com/?userid=1…

这篇对《奔跑吧Linux内核》第一版的内存治理 做了很棒的笔记和总结。《奔跑吧Linux内核》第一版各大书店有售。
这篇文章作者是:Arnold Lu@南京
原文:https://www.cnblogs.com/arnol…

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。

  1. 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.5 slab分配器基于搭档零碎,slab调配更小内存块;以及基于slab的kmalloc;
2.6 vmalloc和kmalloc区别在于v,即在VMALLOC区域调配;
2.7 VMA即Virtual Memory Area,是过程内存治理的外围;
2.8 malloc和2.9 mmap都基于VMA,malloc/free用于调配/开释一块内存;mmap/munmap用于匿名/文件映射到用户空间。以及mmap(补充)。
因为malloc/mmap分配内存并不是立刻调配,只是在用到的时候才会触发2.10 缺页中断解决。
在缺页但页有余的状况下,就须要进行一些操作调整内存,这些操作的根底是2.11 page援用计数,还有页面的2.12 反向映射RMAP技术。
在内存不足状况下触发kswapd2.13 回收页面,其中匿名页面有着非凡的2.14 匿名页面生命周期。
在kswapd回收仍然无奈满足内存调配,就须要对内存进行2.16 内存规整,它依赖的技术是2.15 页面迁徙。
因为内存中存在一些内容齐全一样的页面,应用2.17 KSM技术进行合并,同时利用COW技术,在须要时重新分配。
还介绍了2.18 Dirty COW内存破绽,而后对内存治理数据结构和API进行了总结2.19 总结内存治理数据结构和API。
最初2.20 最新更新和瞻望对新技术进行了介绍。
除了以上技术,还有如下内存技术:

swap计数把匿名页面写入SWAP分区从而开释出闲暇页面

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

zswap技术是zram和swap的一个综合,首先将待换出页面进行压缩,存储到零碎RAM动态分配的内存池中;达到肯定阈值后再写入理论替换设施。

在内存极其有余状况下应用21 OOM(Out-Of-Memory)来杀死不重要过程获取更多内存的技术

基于cgroup的Memory资源管制

解决多媒体对大量间断内存需要的CMA(Contiguous Memory Allocator)技术

slub分配器

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内存治理框架图

  1. 代码和测试环境搭建
    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/b… -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/l… -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命令。

  1. 思考问答
    在系统启动时,ARM Linux内核如何晓得零碎中有多大的内存空间?

在32bit Linux内核中,用户空间和内核空间的比例通常是3:1,能够批改成2:2吗?

物理内存页面如何增加到搭档零碎中,是一页一页增加,还是以2的几次幂来退出呢?

内核的一级页表寄存在什么中央?二级页表又寄存在什么中央?

用户过程的一级页表寄存在什么中央?二级页表呢?

在ARM32零碎中,页表是如何映射的?在ARM64零碎中,页表又是如何映射的?

请简述Linux内核在现实状况下页面分配器(page allocator)是如何调配出间断物理页面的。

在页面分配器中,如何从调配掩码(gfp_mask)中确定能够从哪些zone中分配内存?

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

为用户过程调配物理内存,调配掩码应该选用GFP_KERNEL,还是GFP_HIGHUSER_MOVABLE呢?

slab分配器是如何调配和开释小块内存的?

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

slab调配其中的slab对象有没有依据Per-CPU做一些优化?

slab增长并导致大量不必的闲暇对象,该如何解决?

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

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

假如不思考libc的因素,malloc调配100Byte,那么实际上内核是为其调配100Byte吗?

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

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

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

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

请简述公有映射和共享映射的区别。

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

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

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

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

在Linux 2.4.x内核中,如何从一个page找到所有映射该页面的VMA?反应映射能够带来哪些便当?

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

在Linux 2.6.34中,RMAP机制采纳了新的实现,在Linux 2.6.33和之前的版本中称为旧版本RMAP机制。那么在旧版本RMAP机制中,如果父过程有1000个子过程,每个子过程都有一个VMA,这个VMA外面有1000个匿名页面,当所有的子过程的VMA同时产生写复制时会是什么状况呢?
当page退出lru链表中,被其余线程开释了这个page,那么lru链表如何晓得这个page曾经被开释了。

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

LRU链表如何晓得page的流动频繁水平?

kswapd依照什么准则来换出页面?

kswapd依照什么方向来扫描zone?

kswapd以什么规范来退出扫描LRU?

手持设施例如Android零碎,没有swap分区或者swap文件,kswapd会扫描匿名页面LRU吗?

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

当零碎充斥着大量只拜访一次的文件拜访(use-one streaming IO)时,kswapd如何来躲避这种风暴?

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

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

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

如何了解Refault Distance算法?

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

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

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

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

为什么Dirty COW小程序能够批改一个只读文件的内容?

在Dirty COW内存破绽中,如果Diryt COW程序没有madviseThread线程,即只有procselfmemThread线程,是否批改foo文件的内容呢?

假如在内核空间获取了某个文件对应的page cache页面的struct page数据结构,而对应的VMA属性是只读,那么内核空间是否能够胜利批改该文件呢?

如果用户过程应用只读属性(PROT_READ)来mmap映射一个文件到用户空间,而后应用memcpy来写这段内存空间,会是什么样的状况?

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

请画出在最蹩脚的状况下调配若干个间断物理页面的流程图。

在Android中新增加了LMK(Low Memory Killer),请形容LMK和OOM Killer之间的关系。

请形容一致性DMA映射dma_alloc_coherent()函数在AEM中是如何治理cache一致性的?

请形容流式DMA映射dma_map_single()函数在ARM中是如何治理cache一致性的?

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

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据