为什么我的Linux内核不能回收它的slab内存?

我有一个系统遭受不断增加的内存使用,直到它达到交换的地步,即使是世俗的东西,因此变得非常没有反应。 罪魁祸首似乎是内核分配的内存,但我很难搞清楚内核中到底发生了什么。

我怎么知道哪些内核线程/模块/任何内核内存使用的特定块负责?

下面是一段时间内系统内存使用情况的图表:

系统内存使用情况slab_unrecl随时间增长

随时间增长的slab_unrecl值对应于/proc/meminfoSUnreclaim字段。

当我将slabtop运行到该图的末尾并按高速caching大小对其进行sorting时,以下显示的是:

  Active / Total Objects (% used) : 15451251 / 15530002 (99.5%) Active / Total Slabs (% used) : 399651 / 399651 (100.0%) Active / Total Caches (% used) : 85 / 113 (75.2%) Active / Total Size (% used) : 2394126.21K / 2416458.60K (99.1%) Minimum / Average / Maximum Object : 0.01K / 0.16K / 18.62K OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME 3646503 3646503 100% 0.38K 173643 21 1389144K kmem_cache 3852288 3851906 99% 0.06K 60192 64 240768K kmalloc-64 3646656 3646656 100% 0.06K 56979 64 227916K kmem_cache_node 1441760 1441675 99% 0.12K 45055 32 180220K kmalloc-128 499136 494535 99% 0.25K 15598 32 124784K kmalloc-256 1066842 1066632 99% 0.09K 25401 42 101604K kmalloc-96 101430 101192 99% 0.19K 4830 21 19320K kmalloc-192 19168 17621 91% 1.00K 599 32 19168K kmalloc-1024 8386 7470 89% 2.00K 525 16 16800K kmalloc-2048 15000 9815 65% 1.05K 500 30 16000K ext4_inode_cache 66024 45955 69% 0.19K 3144 21 12576K dentry 369536 369536 100% 0.03K 2887 128 11548K kmalloc-32 18441 16586 89% 0.58K 683 27 10928K inode_cache 44331 42665 96% 0.19K 2111 21 8444K cred_jar 12208 7529 61% 0.57K 436 28 6976K radix_tree_node 627 580 92% 9.12K 209 3 6688K task_struct 6720 6328 94% 0.65K 280 24 4480K proc_inode_cache 36006 36006 100% 0.12K 1059 34 4236K kernfs_node_cache 266752 266752 100% 0.02K 1042 256 4168K kmalloc-16 134640 133960 99% 0.02K 792 170 3168K fsnotify_mark_connector 1568 1461 93% 2.00K 98 16 3136K mm_struct 1245 1165 93% 2.06K 83 15 2656K sighand_cache 

结论:

  • 内核的slab分配器使用大约2.3 GB的RAM
  • 几乎所有这一切都是不可思议的
  • 它的大约1.3 GB被kmem_cachecaching占用
  • 另外0.5 GB属于各种大小的kmalloccaching

这是我撞墙的地方。 我还没有想出如何看看这些caching,看看为什么他们变得如此之大(或为什么他们的记忆是不可思议的)。 我怎样才能进一步调查?

perf kmem record --slab将捕获分析数据和perf kmem stat --slab --caller将通过内核符号进行小计。

这并不能解释为什么你的工作量是这样做的。 添加perf record并查看报告以查看调用内核的内容。

kprobes可以跟踪特定的内核堆栈,导致一种分配。 我自己并不是非常熟悉这个,但是请尝试阅读像ebf脚本一样的例子,比如slabratetop 。

在你的主机上也会有所不同。 添加内存以确保您没有调整它的大小。 尝试更新的内核版本或不同的发行版。