我有一台标准的 Linux(Debian 测试)笔记本电脑,带有交换分区。
我用它做了很多实验。其中一些确实非常消耗内存,Linux 默认的行为方式对我来说是一个问题......让我们举一个愚蠢的例子:
- 坐在笔记本电脑前
- 打开终端
- 输入
python
,然后a = [0]*100000000
现在您很可能没有足够的 RAM 来处理这个大列表。 Linux 将填充 RAM,然后是交换区,几分钟后,OOM 杀手将被触发并杀死(几乎)随机服务,并且希望,如果您在适当的时候按下 Ctrl+C,python
并且如果终端仍然有焦点,计算机将再次响应。
我想强制实施一些内存限制,以避免不必要的交换,并拒绝进程分配比我拥有的更多内存(RAM 中)的权利。如果内存需求低于某个限制或由 root 请求,则只需杀死除 root 之外的任何用户中最耗内存的进程。
ulimit -Sv [mem]
我在后面听到了!
嗬嗬! “使用cgroups
通过cgexec
!”第一排有人说!
是的,你说得对:这些确实是非常好的解决方案。但:
我想要的是内核说:“你属于用户富(不是root),你使用了大量内存,我们将耗尽内存。对不起,伙计……现在就去死吧!”
或者:“你到底在做什么?你需要XMB 并且只有yMB 可用。是的,SWAP 是空的,但是你不会打算用 SWAP 来做你的肮脏工作吧?不,我说不!没有你的记忆!你再坚持的话,你就死定了!”
答案1
有人在你耳边建议cgroups
。好吧,尝试寻找那个方向,因为它可以为您提供:
- 应用于您选择的一组任务(因此不是系统范围的,而是每个进程的)
- 为该组设置了限制
- 限制是静态的
- 他们可以对内存和/或内存+交换强制实施硬限制
类似的东西可以给你带来更接近你的目标:
group limited {
memory {
memory.limit_in_bytes = 50M;
memory.memsw.limit_in_bytes = 50M;
}
}
这说明这个cgroup下的任务最多只能使用50M内存,50M内存+swap,所以当内存满时,不会交换,但如果内存未满,可以将一些数据映射到交换,这是可以允许的。
这是摘录自cgroup的内存文档:
通过使用memsw limit,您可以避免由于交换空间不足而导致的系统OOM。
答案2
我经常遇到同样的问题。我的一般工作流程涉及 MATLAB 中的大量计算。有时我会无意中尝试分配超出可用内存量的新变量。系统挂起,我通常必须硬重启机器才能恢复工作。 :P
就我而言,听起来也像你的情况一样,我不太关心将 MATLAB 使用的内存量限制为静态量 - 我对没有冻结的机器感兴趣,并且我愿意牺牲我的 MATLAB 进程以保持系统响应能力。
受到回应的启发这个帖子,我编写了以下脚本(我将其命名为watch_memory.sh):
#!/bin/bash
MONITOR=$(free | grep 'buffers/cache:')
MEM_USED=$(echo $MONITOR | awk '{ print $3 }')
MEM_FREE=$(echo $MONITOR | awk '{ print $4 }')
MEM_PERC=$(( 100*MEM_USED / (MEM_FREE+MEM_USED) ))
while :; do
if [ "$MEM_PERC" -gt "95" ]
then
kill $1
echo "$1 killed for using too much memory."
exit
fi
sleep 1
MONITOR=$(free | grep 'buffers/cache:')
MEM_USED=$(echo $MONITOR | awk '{ print $3 }')
MEM_FREE=$(echo $MONITOR | awk '{ print $4 }')
MEM_PERC=$(( 100*MEM_USED / (MEM_FREE+MEM_USED) ))
done
该脚本每秒检查可用内存的百分比。当系统耗尽时,你的“替罪羊”pid(作为脚本的参数传递)就会被杀死。
在不调整脚本优先级(niceness)的情况下,替罪羊大约花了10-20秒才被杀死,但它仍然有效。以负优先级运行脚本会导致违规后立即终止(本例中的 11916 是我在内存不足时想要终止的 pid):
sudo nice -n -5 bash watch_memory.sh 11916