这两天办公用的 Ubuntu 总是在内存将用尽的时候死机,所有的界面卡住不同,进 tty 用 top 看一眼后发现 kswapd0 这个进程竟然占用 90~100% 左右的 CPU,网上一查说这个进程是用来管理虚拟内存的。

一般的 Linux 都会有 RAM,swap, 和 EXT4 这几个部分,EXT4 分区就是用来存放一般的文件,可以在机械硬盘或者 SSD 上划分出 ext4 分区来保存文件,相对 RAM(内存)来说要稍微慢一些,RAM 就是日常所说的内存,用来做程序运行时的高速缓存,而 SWAP 是交换分区,一般在物理内存比较小的机器上会划分一块物理磁盘来作为 swap 分区。

swap top

swap 分区是一款虚拟的 RAM,一般在 HDD/SSD 上,当运行比较小的物理内存时,可能经常缺内存,那么系统就会使用 swap 分区,将物理内存中的内容搬迁到 swap 分区中暂存。当可用物理内存比较小的时候,kswapd0 进程就会将相对比较不常用的程序移动到 swap 分区中,这个时候就可能造成这些程序比较卡顿。加入又一台机器物流内存是 4G,而要运行一个需要 5G RAM 的游戏,那么至少有 1G 的内存会放到 swap 分区中。kswapd0 移动内存的过程就会造成 CPU 的大量使用。要解决这个问题有这样几个方式。

在网络上有些教程会提醒用户,当计算机使用了比较大的物理内存的时候,就不需要划分 swap 分区了,一定程度上这种说法也没问题,但是如果 disable swap 分区后,如果遇到程序内存泄漏或者物理内存用完的情况,那么整个计算机就会进入卡死状态。所以推荐还是不要禁用 swap,虽然 swap 分区不会有 RAM 那么快,但是当 RAM 耗尽的时候,swap 分区可以提供一层额外的保护。如果对 swap 比较感兴趣,可以参考这里 阅读更多的相关知识。1

在 askubuntu 的回答中有句话说的很好

Just realize that the SWAP is a failsafe for the RAM.

failsafe 及时发生了故障也要有故障保护机制,否则系统就会 fail.

配置 /etc/sysctl.conf

配置 /etc/sysctl.conf 文件,来告诉 kswapd0 进程只有当物理内存用尽的时候再做移动内存的事情

echo vm.swappiness=0 | sudo tee -a /etc/sysctl.conf

这里 0 表示物理内存还剩余的百分比,这个值的取值范围是 0-100,配置 0 也就意味着只有当没有物理内存可用时再执行 kswapd0.

关闭一些不用的程序

降低或者减少物理内存的使用,也可以降低 kswapd0 过于频繁执行的问题。

购买更多物理内存

一劳永逸的解决内存短缺的问题。也就是换内存条。

手动添加 swap 分区

因为工作的 Ubuntu 是从一盘机械硬盘复制到 SSD 中的,当时 swap 分区没有划分,如果要手动添加 swap 分区可以如下操作。

根据详细的步骤,分区,以及格式化参考之前的文章

编辑 /etc/fstab 文件,增加新的 swap 分区:

sudo vi /etc/fstab

增加类似这样一行:

UUID=735b3be3-779c-4d21-a944-b033225f3ab4 none   swap    sw      0       0

分区的 UUID,可以通过 blkid 命令来获取:

sudo blkid /dev/sda2

假设 /dev/sda2 就是划分的新的 swap 分区。