我正在摆弄我的系统并找到了一种耗尽内存的新方法,但似乎 less 命令在停止/终止命令之前只能保存有限量的数据。
为了测试,运行(小心!很快就会消耗大量系统内存!)
$ cat /dev/zero | less
从我的测试来看,当 less 达到 2.5 GB 的内存后,该命令似乎就会被终止,但我在手册页中找不到任何表明它会以这种方式限制它的内容。
此外,我无法通过谷歌找到有关该主题的任何文档。
对这一相当令人惊讶的发现的任何解释都将非常有用!
系统信息:四核英特尔 i7,8GB 内存。
$ uname -a
Linux Tyler-Work 3.13.0-32-generic #57-Ubuntu SMP Tue Jul 15 03:51:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ less --version
less 458 (GNU regular expressions)
Copyright (C) 1984-2012 Mark Nudelman
less comes with NO WARRANTY, to the extent permitted by law.
For information about the terms of redistribution,
see the file named README in the less distribution.
Homepage: http://www.greenwoodsoftware.com/less
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 14.04 LTS
Release: 14.04
Codename: trusty
更新:
在达到 2.5 GB 的 RAM 使用量后,less 进程仍然存在,但它会停止收集通过管道传入的进程输出的输入。检查返回值表明 cat 进程正在被来自 less 的信号杀死。
$ cat /dev/zero | less; echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
141 0
退出状态 141 表明 less 正在通过 SIGPIPE 终止 cat 进程(https://stackoverflow.com/questions/19120263/why-exit-code-141-with-grep-q#answer-19120674)
从可执行文件本身收集的信息表明,较小的二进制文件是 64 位,因此它在可使用的 RAM 数量上不应受到限制:
$ file /bin/less
/bin/less: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=539cf624699477e3e069b6c4e4b33842f22be2d2, stripped
这并不能解释为什么 less 会以这个特定量的数据向 cat 进程发送终止信号。
答案1
可能会有几件事,less的源代码会让你更深入地了解正在发生的事情。
less 是 32 位应用程序吗?如果是,那么根据你的内核配置,你可能有 3gb、3.5 gb 或(略低于)4 gb 的用户空间。
less 很可能使用 malloc() 将大块内存分配到所谓的堆上。堆限制是什么?这取决于内核配置和其他因素。在某个时候,less 可能正在请求内存,而系统说它无法获得任何内存。它会想“我无法获得内存,我无法前进,我真的应该退出,因为我跟不上队伍了”。
为什么是 2.5G?不知道,有时你的堆分配器不是完全高效的。你可能有 3Gb 的空闲空间,但是因为你需要将块组合在一起,所以实际上你得到的分配量较低,并且会显示一些空闲空间。我记得我们有一个程序只使用了 3.5Gb 堆中的 2GB。小分配将堆碎片化得如此之多,以至于我们几乎无法得到我们想要的一半。请记住,malloc 需要既快又好,有时快胜过好。它不像俄罗斯方块那样知道如何完美地匹配东西,它用打包效率换取时间。使用不同的分配器将是一个有趣的实验(如果你知道如何将它与 LD_PRELOAD 一起使用,Google 的 tcmalloc 似乎特别老旧)。
另外,它被杀死了吗?还是它死了?在它结束后执行 echo $?,如果它自己退出,你应该看到一个数字< 127,或者如果信号杀死了它,则应该看到> 128。如果它被杀死了,也许你的系统内存收割机杀死了它,尽管有 8Gb 的 RAM,如果你的系统觉得有必要这样做,我会感到惊讶。
因此,简而言之,可能是 32 位程序,+ 一些内核约束,+ 低效分配器,+ 较少的分配模式。但请检查返回值以查看是否可能是内存不足收割机将其杀死。