漫游 Linux 内核内存管理:参数、分配与布局的深度探索

/proc/meminfo 显示系统内存状态。

MemTotal:物理内存总量。
MemFree:真正释放内存。
MemAvailable:可以快速回收以供新程序使用。

缓冲区:块设备缓冲区。
缓存:文件数据缓存。
Slab:内核数据结构缓存。

SwapTotal:交换空间总量。
SwapFree:释放交换空间。

AnonPages:匿名页面,例如程序堆栈。
Mapped:文件映射页面。
Shmem:共享内存。

Mlocked:显式锁定内存。
Unevivictable:内存总量不能被换出。

Comfilled_AS:虚拟内存已提交。
CommitLimit:虚拟内存的上限。

VmallocTotal:vmalloc虚拟地址空间大小。

kmalloc:保证物理连续性,适合小对象。

vmalloc:保证虚拟连续性,适合大对象。

alloc_pages:物理上连续的底层页面分配。

内核空间位于高位,用户空间位于低位。

未映射区域:用户空间和内核空间之间。

用户空间:处理唯一的代码数据。

内核代码段:存放内核指令。

内核数据段:存储内核变量。

物理内存直接映射:物理地址一对一映射。

vmalloc区域:虚拟连续但物理不连续。

模块区:内核模块内存。

Fixmap:固定映射物理地址。

PCI/IO映射:设备MMIO映射。

vmemmap:存储structpage结构。

KASANShadow:KASAN 影子内存。

虚拟内存:给进程一种独立地址空间的错觉。

每个进程都有一个独立的页表。

交换空间:物理内存耗尽时交换出去。

页面错误:访问交换页时触发。

brk:调整程序断点地址,扩展堆。

mmap:创建独立的匿名内存区域。

每个CPU计数器:每个CPU独立复制。

优点:高频本地更新操作效率高。

全局总计:遍历所有CPU累加计数器值。

linux内核: overcommit 参数

哎呀,说到Linux内核中的overcommit参数,着实让我头疼了一阵子。
记得2 01 5 年接手一个大型数据处理项目的时候,服务器的内存占用非常巨大。

当时我就遇到了这个问题。
项目需求是处理大量数据,内存占用非常大。
这会导致系统在执行后经常出现内存不足的情况。
当时看了一下,发现这是overcommit参数导致的。

我开始研究这个参数。
主要有三个设置值:OVERCOMMIT_GUESS(值为0)、OVERCOMMIT_ALWAYS(值为1 )、OVERCOMMIT_NEVER(值为2 )。
我当时选择了OVERCOMMIT_GUESS,因为我认为这样可以提高内存使用效率,同时保证系统稳定性。

因此,这个产品相当智能。
它根据当前可用的页框来决定是否允许虚拟内存申请。
然而,该产品并不是万能的,有时仍然会造成陷阱。
例如,我的服务器物理内存只有3 2 GB。
项目一上线,内存消耗爆炸,服务器几乎崩溃。

后来我检查了overcommit_kbytes和overcommit_ratio这两个参数。
overcommit_kbytes是设置允许使用的虚拟内存量,overcommit_ratio是允许使用的虚拟内存与总物理内存的比例。
我当时将overcommit_ratio设置为2 00%,因为我认为应该满足要求。

但是,这个产品并不是万能的,因为系统有时会根据当前可用的页框来决定是否允许虚拟内存申请。
所以我设置了admin_reserve_kbytes和user_reserve_kbytes来为root用户和用户空间保留一些内存。

最后,我使用__vm_enough_memory函数来确定当前是否有足够的可用内存。
该函数根据overcommit_memory的设置值、vm_commit_limit计算出的允许虚拟内存大小以及为root用户和用户进程保留的内存大小来确定是否允许虚拟内存请求。

总之,这个过度使用的参数确实让我失去了很多理智。
不过,当你理解了之后,感觉还是蛮有趣的。
现在回想起来,那段时间的坎坷确实让我成长了很多。
你好,我把这个经验分享给你,希望对你有帮助。

[知识讲解篇-158] Linux内核参数之rp_filter