我很难理解交换策略。我安装了具有 4gb 交换分区的系统(ubuntu 13.04,但 12.10 有同样的问题),因为 ux31a 有 4gb 内存。
问题是每次系统内存不足并开始写入交换时,它都会停止响应。冻结约 5 分钟。
因此,在阅读了一些资料后,我认为也许我应该将 swapiness 设置为 10,然后我就这么做了。系统内存不足后,问题依然存在。
然后我读到 SSD 不应该有任何交换,并且我已设置为在系统启动时关闭交换
现在我已关闭交换功能并且我的 free -m 看起来像:
total used free shared buffers cached
Mem: 3840 3340 499 0 33 1293
-/+ buffers/cache: 2013 1827
Swap: 0 0
不幸的是,问题仍未解决。看起来缓冲区/缓存占用了所有内存,当内存变为 0 时,我遇到了完全相同的问题。我以为缓冲区/缓存应该在需要时自动释放一些内存,但我认为它没有
我该怎么做才能避免系统冻结?
附加信息:当系统在一段时间后冻结时,它可能会响应一些命令,我能够在不同的会话(ctrl + alt + f1)上进入控制台并运行“top”。第一个进程 kswapd0、kworkers 已经消耗了整个 CPU。
预先感谢您的帮助
答案1
我也遇到过 kworker 占用全部内存的问题。这似乎有帮助,以 root 身份运行:
echo N > /sys/module/drm_kms_helper/parameters/poll
互联网上还有其他关于此的帖子
答案2
我和你一样,没有使用交换,为了防止任何此类操作系统冻结,我运行了一个定制内核补丁(也粘贴在下面,但制表符变成了空格),这对我来说是可行的,但由于我不是开发人员,我无法保证它没有做任何不该做的事情。
我在 Qubes OS 4.0 的 dom0 和虚拟机中运行修补后的内核,甚至在内核 4.18.9 和 4.19-rc5 之上应用了它。不过,在 Qubes 的虚拟机中测试它很容易,因为 dom0sudo iotop
可以显示当虚拟机因内存即将耗尽而冻结时发生的磁盘抖动(只读,不写)。问题在于它会逐出可执行文件的代码页,因此每次都必须从磁盘重新读取它们上下文切换。
这里是可以模拟高内存使用率的代码,你可以用它来进行测试。简而言之,就像这样:
$ stress --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 + 4000;}' < /proc/meminfo)k --vm-keep -m 4 --timeout 10s
这里是内核补丁,可避免任何操作系统冻结,仅允许正常触发以oom-killer
终止使用最多 RAM 的进程(但在此粘贴中制表符被空格替换):
revision 3
preliminary patch to avoid disk thrashing (constant reading) under memory pressure before OOM-killer triggers
more info: https://gist.github.com/constantoverride/84eba764f487049ed642eb2111a20830
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 32699b2..7636498 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -208,7 +208,7 @@ enum lru_list {
#define for_each_lru(lru) for (lru = 0; lru < NR_LRU_LISTS; lru++)
-#define for_each_evictable_lru(lru) for (lru = 0; lru <= LRU_ACTIVE_FILE; lru++)
+#define for_each_evictable_lru(lru) for (lru = 0; lru <= LRU_INACTIVE_FILE; lru++)
static inline int is_file_lru(enum lru_list lru)
{
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 03822f8..1f3ffb5 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2086,9 +2086,9 @@ static unsigned long shrink_list(enum lr
struct scan_control *sc)
{
if (is_active_lru(lru)) {
- if (inactive_list_is_low(lruvec, is_file_lru(lru),
- memcg, sc, true))
- shrink_active_list(nr_to_scan, lruvec, sc, lru);
+ //if (inactive_list_is_low(lruvec, is_file_lru(lru),
+ // memcg, sc, true))
+ // shrink_active_list(nr_to_scan, lruvec, sc, lru);
return 0;
}
@@ -2234,7 +2234,7 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,
anon = lruvec_lru_size(lruvec, LRU_ACTIVE_ANON, MAX_NR_ZONES) +
lruvec_lru_size(lruvec, LRU_INACTIVE_ANON, MAX_NR_ZONES);
- file = lruvec_lru_size(lruvec, LRU_ACTIVE_FILE, MAX_NR_ZONES) +
+ file = //lruvec_lru_size(lruvec, LRU_ACTIVE_FILE, MAX_NR_ZONES) +
lruvec_lru_size(lruvec, LRU_INACTIVE_FILE, MAX_NR_ZONES);
spin_lock_irq(&pgdat->lru_lock);
@@ -2345,7 +2345,7 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc
sc->priority == DEF_PRIORITY);
blk_start_plug(&plug);
- while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] ||
+ while (nr[LRU_INACTIVE_ANON] || //nr[LRU_ACTIVE_FILE] ||
nr[LRU_INACTIVE_FILE]) {
unsigned long nr_anon, nr_file, percentage;
unsigned long nr_scanned;
@@ -2372,7 +2372,8 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc
* stop reclaiming one LRU and reduce the amount scanning
* proportional to the original scan target.
*/
- nr_file = nr[LRU_INACTIVE_FILE] + nr[LRU_ACTIVE_FILE];
+ nr_file = nr[LRU_INACTIVE_FILE] //+ nr[LRU_ACTIVE_FILE]
+ ;
nr_anon = nr[LRU_INACTIVE_ANON] + nr[LRU_ACTIVE_ANON];
/*
@@ -2391,7 +2392,8 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc
percentage = nr_anon * 100 / scan_target;
} else {
unsigned long scan_target = targets[LRU_INACTIVE_FILE] +
- targets[LRU_ACTIVE_FILE] + 1;
+ //targets[LRU_ACTIVE_FILE] +
+ 1;
lru = LRU_FILE;
percentage = nr_file * 100 / scan_target;
}
@@ -2409,10 +2411,12 @@ static void shrink_node_memcg(struct pgl
nr[lru] = targets[lru] * (100 - percentage) / 100;
nr[lru] -= min(nr[lru], nr_scanned);
+ if (LRU_FILE != lru) { //avoid this block for LRU_ACTIVE_FILE
lru += LRU_ACTIVE;
nr_scanned = targets[lru] - nr[lru];
nr[lru] = targets[lru] * (100 - percentage) / 100;
nr[lru] -= min(nr[lru], nr_scanned);
+ }
scan_adjusted = true;
}
注意:我不建议在生产环境中使用这个补丁。正如我所说,我不是开发人员,这个补丁更像是一个概念验证:Active(file)
当内存压力很大时,它会尝试不从 RAM 中逐出页面,因此上下文切换在执行期间不必从磁盘重新读取可执行文件,因此它不会因为从磁盘重新读取这些可执行文件的速度缓慢而导致操作系统冻结。