碎片整理 RAM / OOM 失败

Old*_*oil 11 linux memory embedded

这个问题相当长,所以我会在顶部提出问题,然后通过我的方法来回答问题:

  1. (基于 Busybox 的)rm 是否因为没有足够的连续 RAM 而没有执行?
  2. 如果是这样,是否有一种轻量级的方法来对 DMA 进行碎片整理 - 而无需求助于系统重新启动?
  3. 如果不是,是什么原因造成的?我怎样才能防止它在未来发生?

在我们的测试系统在过去几天相当密集地运行之后 - 我 telnet 进入系统并检查了测试结果。当我来删除一些数据时,系统返回了命令行(好像命令执行正确一样)。当我来检查目录以获取另一组结果时,我看到该文件仍然存在(使用 ls)。

在此之后,我注意到越来越多的 shell 命令没有按预期执行。

在 rm 无法正确执行后,我将从dmesg的输出开始:

从进程 6821 (rm) 分配长度 61440 失败

每个 CPU 的 DMA:

CPU 0: hi: 0, btch: 1 usd: 0

Active_anon:0 active_file:1 inactive_anon:0 inactive_file:0 unevictable:6 脏:0 回写:0 不稳定:0 空闲:821 平板:353 映射:0 页表:0 弹跳:0

DMA free:3284kB min:360kB low:448kB high:540kB active_anon:0kB inactive_anon:0kB active_file:4kB inactive_file:0kB unvictable:24kB present:8128kB pages_scanned:0 all_unreclaimable?不

lowmem_reserve[]: 0 0 0

DMA:31*4kB 47*8kB 42*16kB 64*32kB 1*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 3284kB

总共 14 个页面缓存页面

无法为过程数据分配 RAM,错误号 12

最初,我以为我无法在连续内存的最大部分运行程序。这意味着 DMA 太碎片化了,我必须找到一种方法让系统对内存进行碎片整理。

然后我做了一个快速的数学/完整性检查,意识到程序应该能够在唯一的 64kB 连续内存插槽中运行。Rm 请求 61440 字节 (60kB)。

我做了一个很好的旧“手动碎片整理”并重新启动了系统。当我重新启动系统时,我输出 /proc/buddyinfo:

Node 0, zone DMA 2 8 3 12 0 1 0 1 0 1 0

我怀疑映射到:

  • 2 x 4 KB
  • 8 x 8 KB
  • 3 x 16 KB
  • 12 x 32 KB
  • 1 x 128 KB
  • 1 x 512 KB

但是,如果对上述值列表求和,则它与/proc/meminfo的输出不匹配:

MemTotal:           6580 kB
MemFree:            3164 kB
Buffers:               0 kB
Cached:              728 kB
SwapCached:            0 kB
Active:              176 kB
Inactive:            524 kB
Active(anon):          0 kB
Inactive(anon):        0 kB
Active(file):        176 kB
Inactive(file):      524 kB`
Unevictable:           0 kB
Mlocked:               0 kB
MmapCopy:            844 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:             0 kB
Mapped:                0 kB
Slab:               1268 kB
SReclaimable:        196 kB
SUnreclaim:         1072 kB
PageTables:            0 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:        3288 kB
Committed_AS:          0 kB
VmallocTotal:          0 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB
Run Code Online (Sandbox Code Playgroud)

回顾一下,我的问题是:

  1. rm 没有执行是因为没有足够的连续 RAM 吗?
  2. 如果是这样,是否有一种轻量级的方法来对 DMA 进行碎片整理 - 而无需求助于系统重新启动?
  3. 如果不是,是什么原因造成的?我怎样才能防止它在未来发生?

我正在使用运行 uClinux 2.6.30 版的 Lantronix 的 XPort Pro(8MB,Linux 操作系统)。正在使用的外壳是安静的。

And*_*ner 11

关于您的问题 2(对内存进行碎片整理),引用自https://www.kernel.org/doc/Documentation/sysctl/vm.txt:

紧凑内存

仅在设置 CONFIG_COMPACTION 时可用。当 1 写入文件时,所有区域都会被压缩,以便在可能的情况下在连续块中提供可用内存。这在例如分配大页面时可能很重要,尽管进程也会根据需要直接压缩内存。

这意味着以下命令(以 root 权限执行,并且如果启用了上述内核选项)

echo 1 > /proc/sys/vm/compact_memory
Run Code Online (Sandbox Code Playgroud)

应该告诉内核尽可能多地尝试对内存进行碎片整理。请注意,例如在某些 RHEL6 版本上,这可能会导致内核崩溃...


Old*_*oil 7

这花了一些时间,但我想我会推迟回答,直到我回答了所有 3 个子问题。

不过,在开始之前,我会提到,当谈到“碎片化”工作记忆时,正确的术语是“压缩”工作记忆。

1. rm 没有执行是因为没有足够的连续 RAM 吗?

我的结论是正确的 - rm 没有执行,因为没有足够的连续 RAM。该系统一直在获取 RAM 并将其碎片化,从而使其无法回收。

2. 如果是这样,是否有一种轻量级的 DMA 碎片整理方法——无需重新启动系统?

事实证明,除了重新启动嵌入式系统之外,没有办法压缩内存。在无 MMU 系统的情况下,预防就是游戏的名称。

我的一部分在思考是否有可能破解 linux 内核以在软件中模拟 MMU。我想如果有可能的话,早就有人做了。我无法想象这是一个全新的概念;)

3. 我怎样才能防止它在未来发生?

对于这个项目,每次需要时我都使用 cron 手动启动程序。一个更好的方法是在启动时调用程序,然后强制程序休眠直到需要它。这样,不需要在每次使用时分配内存。从而减少碎片化。

在项目的第一次迭代中,我们依靠我的 shell 脚本调用来执行关键功能(例如 rm)。如果我们不需要,我们认为没有必要重新发明轮子。

但是,对于无 MMU 的系统,我建议尽可能避免使用 shell -

(问题,如果你执行会发生什么ls -la /path/to/directory/ | grep file-i-seek?)

(答案:它启动一个新的子进程)

如果您需要在 C 程序中实现一些核心 shell 脚本功能,我建议您查看BusyBox 中使用的源代码。很有可能你会在你的嵌入式系统中使用 C..

  • [我意识到这很旧] 模拟 MMU 很难......如果没有 MMU,每个程序都会直接使用出现在内存总线上的物理地址。您可以模拟一个,但您必须拦截每个内存访问(就像实际的 MMU 一样)。性能会很糟糕。或者,您可以使用间接指针(就像 Mac OS Classic 所做的那样,称它们为“句柄”),但是您有一个完全困难的 API,并且在抢占面前非常困难(Mac OS Classic 使用协作式多任务处理) . (3认同)