nib*_*bot 21 memory freeze swap ubuntu
我们都经历过它——一些程序被要求做一些需要大量内存的事情。它尽职尽责地尝试分配所有这些内存,系统立即开始抖动,无休止地交换并变得缓慢或无响应。
我最近在我的 Ubuntu 笔记本电脑上遇到了这个问题,因为一个 Matlab 脚本试图分配一个非常大的矩阵。经过约 5 分钟的颠簸后,我能够按 Ctrl-F1 到控制台并杀死 Matlab。我宁愿有一些热键,它可以让我立即控制系统并允许我终止有问题的进程;或者,也许只是默默地拒绝分配如此大的缓冲区。
重新获得对由于过度交换而变得无响应或极其缓慢的 Linux 系统的控制的最快方法是什么?
有没有一种有效的方法可以首先防止发生这种交换,例如通过限制允许进程尝试分配的内存量?
我为此目的制作了一个脚本 - https://github.com/tobixen/thrash-protect
我已经在生产服务器、工作站和笔记本电脑上运行了这个脚本,并取得了成功。这个脚本不会终止进程,而是暂时挂起它们 - 我后来遇到过几种情况,我很确定如果不是这个简单的脚本,我会因为颠簸而失去控制。在“最坏”的情况下,违规进程将被减慢很多,最终被内核(OOM)杀死,在“最好”的情况下,违规进程将实际完成……无论如何,服务器或工作站将保持相对响应,以便于调查情况。
当然,“购买更多内存”或“不使用交换”是关于“如何避免颠簸?”问题的两种选择,更传统的答案,但总的来说,它们往往效果不佳(安装更多内存可能不是微不足道的,一个流氓进程可以吃掉所有的内存,无论安装了多少,当没有足够的内存用于缓冲/缓存时,即使没有交换,一个人也可能陷入颠簸问题)。我确实推荐 thrash-protect 以及大量交换空间。
- 重新获得对由于过度交换而变得无响应或极其缓慢的 Linux 系统的控制的最快方法是什么?
上面已经用Alt-SysRq-F回答了
- 有没有一种有效的方法可以首先防止发生这种交换,例如通过限制允许进程尝试分配的内存量?
我正在回答这个第二部分。是的,ulimit仍然可以很好地限制单个进程。你可以:
另外,正如简要提到的:
您可以使用 CGroups 来限制资源使用并防止此类问题
事实上,cgroups 提供了更高级的控制,但在我看来,目前配置起来更复杂。
这是一个简单的例子:
$ bash
$ ulimit -S -v $((1*2**20))
$ r2(){r2 $@$@;};r2 r2
bash: xmalloc: .././subst.c:3550: cannot allocate 134217729 bytes (946343936 bytes allocated)
Run Code Online (Sandbox Code Playgroud)
它:
r2(){ r2 $@$@;};r2 r2,该函数调用将在请求堆栈内存时无限加倍,从而以指数方式消耗 CPU 和 RAM。如您所见,当尝试请求超过 1GB 时它停止了。
注意,-v对虚拟内存分配(总的,即物理+交换)进行操作。
限制虚拟内存分配,as相当于-vfor limits.conf。
我执行以下操作以防止任何单个行为不当的过程:
address space limit = <physical memory> - 256MB.一个班轮:
$ sudo bash -c "echo -e \"*\thard\tas\t$(($(grep -E 'MemTotal' /proc/meminfo | grep -oP '(?<=\s)\d+(?=\skB$)') - 256*2**10))\" > /etc/security/limits.d/mem.conf"
Run Code Online (Sandbox Code Playgroud)
为了验证,这会导致以下结果(例如在 16GB 系统上):
$ cat /etc/security/limits.d/mem.conf
* hard as 16135196
$ ulimit -H -v
161351960
Run Code Online (Sandbox Code Playgroud)
笔记:
rss在limits.conf 中使用选项。较新的内核不尊重它。提供更多控制,但目前使用起来更复杂:
memory.max_usage_in_bytes 可以分别核算和限制物理内存。ulimit -m和/或rssinlimits.conf旨在提供类似的功能,但从内核 Linux 2.4.30 起就不起作用了!cgroup_enable=memory swapaccount=1.
cgm 现在似乎是官方支持的用户空间工具。例如检查当前设置:
$ echo $(($(cat /sys/fs/cgroup/memory/memory.max_usage_in_bytes) / 2**20)) MB
11389 MB
$ cat /sys/fs/cgroup/memory/memory.stat
...
Run Code Online (Sandbox Code Playgroud)
例如限制单个进程的内存:
$ cgm create memory mem_1G
$ cgm setvalue memory mem_1G memory.limit_in_bytes $((1*2**30))
$ cgm setvalue memory mem_1G memory.memsw.limit_in_bytes $((1*2**30))
$ bash
$ cgm movepid memory mem_1G $$
$ r2(){ r2 $@$@;};r2 r2
Killed
Run Code Online (Sandbox Code Playgroud)
要查看它在运行时将 RAM 作为后台进程咀嚼然后被杀死:
$ bash -c 'cgm movepid memory mem_1G $$; r2(){ r2 $@$@;};r2 r2' & while [ -e /proc/$! ]; do ps -p $! -o pcpu,pmem,rss h; sleep 1; done
[1] 3201
0.0 0.0 2876
102 0.2 44056
103 0.5 85024
103 1.0 166944
...
98.9 5.6 920552
99.1 4.3 718196
[1]+ Killed bash -c 'cgm movepid memory mem_1G $$; r2(){ r2 $@$@;};r2 r2'
Run Code Online (Sandbox Code Playgroud)
请注意内存请求的指数(2 的幂)增长。
将来,让我们希望看到“发行版/供应商”为 SSH 和图形堆栈等重要事物预先配置 cgroup 优先级和限制(通过 systemd 单元),这样它们就永远不会出现内存不足的情况。
| 归档时间: |
|
| 查看次数: |
11461 次 |
| 最近记录: |