我正在开发基于 ARM 的嵌入式平台。 32 位,512MB RAM,无交换区。 Linux 3.10.53(Ubuntu 的某种变体,如果相关的话)。
我正在处理的一些代码不断地被 oom 杀死,尽管我实际测量到的所有内容都表明当它死掉时有足够的内存可用。可能是什么原因造成的?
在运行该进程之前,free -m 报告约320MB免费,也接近 /proc/meminfo 中的 LowFree 数字; ps -e -o vsize 中的所有数字之和约为 212MB,/proc/meminfo 中的平板数据约为 10MB,这间接表明不应使用超过 222MB 的空间,这与以下数据大致一致空闲内存。
然后我运行我的代码,过了一会儿它就被 oom 杀死了。 dmesg 中的注释说该过程有一个总大小 180MB;请注意,这比运行之前据称免费的 300MB 左右要少得多。正是这个进程自己的内存请求触发了 oom-killer。
(这绝对是 oom-killer 杀死了进程;它在 dmesg 中说了这么多,而我的 ulimit 是无限的。)
一个简单的程序
我发现我可以使用一个绝对简单的程序来重现我不理解的关键问题。我将对此进行描述,然后(如果有人关心)返回到最初发送给我的更复杂的程序,我已经在该程序上进行了更广泛的测试。
所以,这里有一些代码。无聊的#includes被省略了。普通的C.
int main(void) {
int i=0, j;
char * p;
while (1) {
fprintf(stderr, "allocating block %d\n", ++i);
p = malloc(10000000);
for (j=0; j<10000000; ++j) p[j] = j; /* touch memory */
}
return 0;
}
在运行此程序之前,似乎有大约 320MB 的可用空间。它分配 16 个 10MB 块,然后在尝试分配第 17 个块时被 oom-killed。
好的,现在回到原来的程序。
这个节目最初是关于
如果我使用 strace -e trace=memory 运行进程(以便我看到对 brk 和 m[un]map2 的调用):首先,输出似乎与 180MB 进程大小一致;其次,进程在 oom-killed 之前执行的最后一次分配约为 15MB。
如果我在 gdb 下运行该进程并尽可能停止它直到它终止,那么:
- /proc/meminfo 的 LowFree 数字仍然约为 230MB
- /proc/meminfo 中的其他数字似乎都没有表明已使用其他内存(例如,slab 仍然约为 10MB,因此该进程似乎并没有以某种方式使内核分配很多内存)
- ps 报告该进程的 vsize 约为 165MB(这与 15MB 分配使其达到 180MB 一致,这显然是 oom-killer 杀死它时的情况)
- gdb
info proc mappings
没有显示任何对我来说可疑的内容,[编辑添加:]除了那- 它列出的区域之一的名称类似于
[stack:14958]
,数字是我的一个线程的 LWP ID,大小似乎约为 130MB,即使代码中的所有大内存分配都是通过malloc
或在堆上进行的new
。有一个地区叫 ,heap
但它要小得多。 - 跟踪进程表明所有这些大内存分配实际上都是在幕后映射的;我想这足以解释这一点(因此“堆栈”名称具有误导性);但我无知,因此不确定。 (我已经验证这些 mmap 调用返回的内存块确实位于该区域内。)
- 它列出的区域之一的名称类似于
(可能相关:当停止在那里时,gdb 开始表现奇怪——例如,continue
让它说“警告:无法获取通用寄存器”并且显然无法继续运行程序)这似乎可以想象是由某种资源触发的筋疲力尽。)
[编辑补充:在 gdb 下运行时,进程会提前终止,这并不奇怪,因为 gdb 本身使用了不可忽略的内存量。确切地说,它何时在 gdb 下死亡显然取决于我设置的断点。]
这都是在 vm.overcommit_memory=0 和 vm.overcommit_ratio=50 的情况下实现的。将过量使用比率增加到 90 似乎没有任何改变(但我已经验证 meminfo 中的 CommitLimit 数字适当增加)。
设置 vm.overcommit_memory=2 (我理解应该关闭过度使用)似乎不会改变任何东西,这让我有点困惑(禁用过度使用不应该使分配在进行时失败,而不是成功然后触发oom 杀手?)。
以下是我认为 oom-killer 日志中最相关的信息:
Sep 24 11:02:04 wandboard kernel: MY_PROCESS_NAME invoked oom-killer: gfp_mask=0x2084d0, order=0, oom_score_adj=0
Sep 24 11:02:04 wandboard kernel: CPU: 0 PID: 14294 Comm: MY_PROCESS_NAME Not tainted 3.10.53-1.1.0_ga-wandboard-06034-g13bb184-dirty #1
Sep 24 11:02:04 wandboard kernel: [<80013acc>] (unwind_backtrace+0x0/0xf8) from [<80011544>] (show_stack+0x10/0x14)
Sep 24 11:02:04 wandboard kernel: [<80011544>] (show_stack+0x10/0x14) from [<8067d0cc>] (dump_header.isra.10+0x64/0x188)
Sep 24 11:02:04 wandboard kernel: [<8067d0cc>] (dump_header.isra.10+0x64/0x188) from [<80092170>] (oom_kill_process+0x270/0x3c8)
Sep 24 11:02:04 wandboard kernel: [<80092170>] (oom_kill_process+0x270/0x3c8) from [<80092710>] (out_of_memory+0x27c/0x2d4)
Sep 24 11:02:04 wandboard kernel: [<80092710>] (out_of_memory+0x27c/0x2d4) from [<80096568>] (__alloc_pages_nodemask+0x834/0x85c)
Sep 24 11:02:04 wandboard kernel: [<80096568>] (__alloc_pages_nodemask+0x834/0x85c) from [<800ab4a0>] (__pte_alloc+0x24/0x13c)
Sep 24 11:02:04 wandboard kernel: [<800ab4a0>] (__pte_alloc+0x24/0x13c) from [<800ae474>] (handle_mm_fault+0xdc/0xf0)
Sep 24 11:02:04 wandboard kernel: [<800ae474>] (handle_mm_fault+0xdc/0xf0) from [<800185e4>] (do_page_fault+0x208/0x368)
Sep 24 11:02:04 wandboard kernel: [<800185e4>] (do_page_fault+0x208/0x368) from [<80008370>] (do_DataAbort+0x34/0x9c)
Sep 24 11:02:04 wandboard kernel: [<80008370>] (do_DataAbort+0x34/0x9c) from [<8000deb4>] (__dabt_usr+0x34/0x40)
Sep 24 11:02:04 wandboard kernel: Exception stack(0x8b6a1fb0 to 0x8b6a1ff8)
Sep 24 11:02:04 wandboard kernel: 1fa0: 6dd95001 7ed706a8 6cdfffff 000000e6
Sep 24 11:02:04 wandboard kernel: 1fc0: 6dd95001 000006f2 00000603 7ed706c8 0014c0a0 7ed70910 00000003 7ed706f4
Sep 24 11:02:04 wandboard kernel: 1fe0: 6cdffffe 7ed70690 6ce00000 00195a6c 200f0010 ffffffff
Sep 24 11:02:04 wandboard kernel: Mem-info:
Sep 24 11:02:04 wandboard kernel: DMA per-cpu:
Sep 24 11:02:04 wandboard kernel: CPU 0: hi: 42, btch: 7 usd: 33
Sep 24 11:02:04 wandboard kernel: active_anon:44721 inactive_anon:36 isolated_anon:0
Sep 24 11:02:04 wandboard kernel: active_file:7 inactive_file:1 isolated_file:0
Sep 24 11:02:04 wandboard kernel: unevictable:0 dirty:0 writeback:0 unstable:0
Sep 24 11:02:04 wandboard kernel: free:40238 slab_reclaimable:720 slab_unreclaimable:1594
Sep 24 11:02:04 wandboard kernel: mapped:4 shmem:77 pagetables:257 bounce:0
Sep 24 11:02:04 wandboard kernel: free_cma:39999
Sep 24 11:02:04 wandboard kernel: DMA free:160952kB min:1684kB low:2104kB high:2524kB active_anon:178884kB inactive_anon:144kB active_file:28kB inactive_file:4kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:524288kB managed:177468kB mlocked:0kB dirty:0kB writeback:0kB mapped:16kB shmem:308kB slab_reclaimable:2880kB slab_unreclaimable:6376kB kernel_stack:1160kB pagetables:1028kB unstable:0kB bounce:0kB free_cma:159996kB writeback_tmp:0kB pages_scanned:75 all_unreclaimable? yes
Sep 24 11:02:04 wandboard kernel: lowmem_reserve[]: 0 0 0 0
Sep 24 11:02:04 wandboard kernel: DMA: 3486*4kB (UMC) 3056*8kB (UC) 2814*16kB (MC) 2395*32kB (UMC) 14*64kB (MC) 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB 0*8192kB 0*16384kB 0*32768kB = 160952kB
Sep 24 11:02:04 wandboard kernel: 90 total pagecache pages
Sep 24 11:02:04 wandboard kernel: 0 pages in swap cache
Sep 24 11:02:04 wandboard kernel: Swap cache stats: add 0, delete 0, find 0/0
Sep 24 11:02:04 wandboard kernel: Free swap = 0kB
Sep 24 11:02:04 wandboard kernel: Total swap = 0kB
Sep 24 11:02:04 wandboard kernel: 131072 pages of RAM
Sep 24 11:02:04 wandboard kernel: 40500 free pages
Sep 24 11:02:04 wandboard kernel: 4710 reserved pages
Sep 24 11:02:04 wandboard kernel: 1715 slab pages
Sep 24 11:02:04 wandboard kernel: 264131 pages shared
Sep 24 11:02:04 wandboard kernel: 0 pages swap cached
Sep 24 11:02:04 wandboard kernel: [ pid ] uid tgid total_vm rss nr_ptes swapents oom_score_adj name
Sep 24 11:02:04 wandboard kernel: [ 254] 0 254 623 154 3 0 0 upstart-udev-br
Sep 24 11:02:04 wandboard kernel: [ 269] 0 269 2377 156 6 0 -1000 systemd-udevd
Sep 24 11:02:04 wandboard kernel: [ 290] 103 290 889 139 5 0 0 dbus-daemon
Sep 24 11:02:04 wandboard kernel: [ 348] 0 348 826 46 4 0 0 bluetoothd
Sep 24 11:02:04 wandboard kernel: [ 363] 0 363 841 74 5 0 0 systemd-logind
Sep 24 11:02:04 wandboard kernel: [ 436] 109 436 705 86 5 0 0 avahi-daemon
Sep 24 11:02:04 wandboard kernel: [ 441] 101 441 7429 206 9 0 0 rsyslogd
Sep 24 11:02:04 wandboard kernel: [ 444] 109 444 675 55 5 0 0 avahi-daemon
Sep 24 11:02:04 wandboard kernel: [ 539] 0 539 1810 176 7 0 0 cups-browsed
Sep 24 11:02:04 wandboard kernel: [ 603] 0 603 486 45 3 0 0 upstart-socket-
Sep 24 11:02:04 wandboard kernel: [ 606] 0 606 621 185 5 0 0 upstart-file-br
Sep 24 11:02:04 wandboard kernel: [ 704] 0 704 845 29 5 0 0 getty
Sep 24 11:02:04 wandboard kernel: [ 705] 0 705 845 29 5 0 0 getty
Sep 24 11:02:04 wandboard kernel: [ 709] 0 709 845 29 5 0 0 getty
Sep 24 11:02:04 wandboard kernel: [ 710] 0 710 845 29 5 0 0 getty
Sep 24 11:02:04 wandboard kernel: [ 713] 0 713 845 29 5 0 0 getty
Sep 24 11:02:04 wandboard kernel: [ 734] 0 734 1471 120 6 0 -1000 sshd
Sep 24 11:02:04 wandboard kernel: [ 742] 0 742 565 45 5 0 0 cron
Sep 24 11:02:04 wandboard kernel: [ 998] 0 998 845 29 5 0 0 getty
Sep 24 11:02:04 wandboard kernel: [ 999] 0 999 407 28 5 0 0 getty
Sep 24 11:02:04 wandboard kernel: [ 1024] 1000 1024 676 47 4 0 0 ssh-agent
Sep 24 11:02:04 wandboard kernel: [ 8516] 0 8516 1729 222 7 0 0 cupsd
Sep 24 11:02:04 wandboard kernel: [13071] 0 13071 6958 244 11 0 0 console-kit-dae
Sep 24 11:02:04 wandboard kernel: [13136] 0 13136 8426 155 10 0 0 polkitd
Sep 24 11:02:04 wandboard kernel: [13482] 0 13482 2458 192 8 0 0 sshd
Sep 24 11:02:04 wandboard kernel: [13501] 1000 13501 2458 195 8 0 0 sshd
Sep 24 11:02:04 wandboard kernel: [13504] 1000 13504 1491 553 6 0 0 bash
Sep 24 11:02:04 wandboard kernel: [14291] 0 14291 1432 104 5 0 0 sudo
Sep 24 11:02:04 wandboard kernel: [14294] 0 14294 45100 41145 89 0 0 MY_PROCESS_NAME
Sep 24 11:02:04 wandboard kernel: Out of memory: Kill process 14294 (MY_PROCESS_NAME) score 316 or sacrifice child
Sep 24 11:02:04 wandboard kernel: Killed process 14294 (MY_PROCESS_NAME) total-vm:180400kB, anon-rss:164580kB, file-rss:0kB
如果我理解正确的话(一个很大的如果),order=0 表示我们一次只请求一个页面,这似乎排除了碎片作为罪魁祸首。该报告本身表明有很多空闲页面。这是怎么回事?