进一步阅读

进一步阅读

我的笔记本电脑有足够的 RAM 和 SSD。为了不磨损 SSD,我不希望使用交换空间。如果某个进程使用了​​太多 RAM,以至于必须开始使用交换空间,那么它显然是行为不当,应该被内核杀死。但我还希望能够使我的笔记本电脑休眠或混合睡眠。目前似乎很难让这样的设置正常工作。以下是一些注意事项:

  • 即使设置swappiness为 0,如果应用程序请求的内存过多,也会使用交换空间。似乎没有办法启用交换空间,但会阻止内核将其用作交换空间(从而降低其对休眠映像空间的利用率)
  • 暂时禁用交换将导致类似systemctl hibernateerror out 的命令Failed to hibernate system via logind: Sleep verb not supported
  • 我希望 upower 能够使我的系统进入休眠/混合睡眠状态(因此编写一个启用交换然后启动的包装脚本systemctl hibernate是不够的)

我现在正在寻找实现此目的的正确方法。一种方法可能是通常禁用我的交换分区,然后swapon通过 systemd 在正确的时间点(以及swapoff系统唤醒后)禁用。但我不知道如何实现这一点。

另一种方法是使用交换文件,但与使用交换分区相比,这似乎增加了额外的复杂性。尤其是因为我使用的是全盘加密,这似乎uswsusp只是在我现有的交换分区上再增加一层。但也许我忽略了一些东西,使用交换文件确实总体上更容易实现这一目的。

答案1

  1. 当你已经知道你的系统可能会出现内存不足的情况时,禁用交换是一种馊主意。当内核没有任何内存可供分配时,你的系统可能会非常非常无响应或挂起,因此您必须重新启动它。挂起可能会导致数据丢失,有时还会导致文件系统损坏。取决于文件系统,它可以自动修复(ext* 系列、fat 系列、btrfs 和其他一些),但并非每个 FS 都支持此功能。我敢打赌,fsck每次出现损坏时,您可能都不喜欢在单用户模式下运行……

  2. 内核不会愚蠢到将想要的所有内容都写入 SSD,它的行为与 HDD 不同,会尝试使用诸如 TRIM 之类的东西尽可能少地写入。这对您的驱动器造成的损害并不像您想象的那么大。

  3. 冬眠是一种内置在低层运行的内核子系统。它仍然必须有一个单独的分区,其大小≥RAM 大小,以便它能够对内存进行完整快照。这里您可以阅读 Linux 如何管理休眠。如果没有地方永久存储内存映像,休眠就无法工作。您无法将数据存储在空中。没有永久物理存储 = 没有休眠。所以这也是您问题的答案:在 Linux 上,如果没有交换分区,则无法使用休眠模式

因此,我的观点是,您当然可以不使用交换,而只在休眠时启用它,但前提是您确定系统在 99.9% 的时间内都有足够的内存来处理所有事情。如果不是这种情况,则必须使用交换。

现在讨论可能的解决方案:

当您运行systemctl hibernatesystemd 时,会启动一个名为systemd-hibernate.service. 单元文件通常位于/usr/lib/systemd/系统/目录

在 Debian 上它看起来像这样:

#  SPDX-License-Identifier: LGPL-2.1+
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Hibernate
Documentation=man:systemd-suspend.service(8)
DefaultDependencies=no
Requires=sleep.target
After=sleep.target

[Service]
Type=oneshot
ExecStart=/lib/systemd/systemd-sleep hibernate

正如你所看到的需要选项。我们可以编写另一个单元来启用交换并将其名称添加到这些字段。我们将其命名为交换服务并将其放入/etc/systemd/系统/目录

我们的文件看起来会像这样:

# Unit filed is not required in our case so you can skip it
[Unit]
Description=Enable swap partition

[Service]
# This line means that service will be executed just once and immediately stop when
# swapon enables swap on /dev/sda3
Type=oneshot

# Change /dev/sda3 with device named after your swap partition 
# like /dev/sdb3 or /dev/nvme0n1p3
# Use lsblk to determine your swap partition (partition with [SWAP] as mountpoint)
# Of course you can think of a more complex solution like running external script
# that determines your swap partition automatically every time service is executed
# but for now I'll go with simple /dev/sda3
ExecStart=/sbin/swapon /dev/sda3

现在我们应该修改系统的systemd-hibernate.service

#  SPDX-License-Identifier: LGPL-2.1+
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Hibernate
Documentation=man:systemd-suspend.service(8)
DefaultDependencies=no
Requires=sleep.target swap-on.service <--
After=sleep.target swap-on.service <--

[Service]
Type=oneshot
ExecStart=/lib/systemd/systemd-sleep hibernate

我们正在复制交换服务在 After 中确保 systemd 启动休眠交换已打开,而不是相反,并且需要确保 systemd 不会尝试休眠交换服务失败的。

现在当我们运行systemctl hibernatesystemd 时会运行我们修改后的systemd-hibernate.service运行交换服务启用交换。当启用交换并且两个必填字段和 After 字段都满足时,systemd 最终可以让系统进入休眠状态。

为了使 systemd 从休眠状态恢复后禁用交换,我们不需要创建另一个名为的服务文件换货服务它将做与我们相同的事情交换服务,将其放置在与“on”服务相同的目录中(/etc/systemd/system/)。唯一的区别是,此服务将运行交换代替斯瓦彭

[Unit]
Description=Disable swap partition

[Service]
Type=oneshot

#  again, change /dev/sda3 to your swap partition /dev file
ExecStart=/sbin/swapoff /dev/sda3 <--

下一步是修改名为[电子邮件保护]位于同一/usr/lib/systemd/系统目录:

[Unit]
Description=Resume from hibernation using device %f
Documentation=man:[email protected](8)
DefaultDependencies=no
BindsTo=%i.device
Wants=local-fs-pre.target
After=%i.device
Before=local-fs-pre.target
ConditionPathExists=/etc/initrd-release

[Service]
Type=oneshot
ExecStart=/lib/systemd/systemd-hibernate-resume %f

我们需要修改字段。添加换货服务旁边本地文件系统预目标

...
After=%i.device
Before=local-fs-pre.target swap-off.service <--
ConditionPathExists=/etc/initrd-release
...

现在当您从休眠状态恢复时 systemd 将运行换货服务在交换映像加载到内存之后(实际上稍晚一些,但这对我们来说并不重要)

请记住,这是一个完全理论上的解决方案,我还没有尝试过,但根据我对 systemd 的了解,这应该可行。由于 UPower 要求 systemd 休眠,正如我所解释的那样,它会运行 systemd-hibernate.service,所以这可能是你正在寻找的

答案2

首先,你不必担心现在的 SSD。它们的磨损均衡算法已经足够好了,以至于过去几年的 SSD 都有 5 年保修期,这意味着制造商非常有信心,即使你在 5 年内每天向其写入大量数据,驱动器仍能正常工作。SSD 越大,其使用寿命就越长,因为固件有更多的空闲块来移动死簇。但即使是较旧的 SSD 也能承受这种情况。我有一台 2012-2014 年左右生产的旧工作站,其 SSD 刚刚达到总数据写入量的 50%

正如其他人所说,即使你有足够的 RAM,禁用交换也不是一个好主意。因此,你仍然需要某种交换,但你应该忘记普通交换并使用兹拉姆相反。这是快多了比 HDD、SD、eMMC 或旧款 SSD 更不会对闪存造成磨损。使用默认的 lzo 压缩算法,它甚至比许多基于基准测试结果在这里。您可以更改为伊佐尔勒lz4(即比 lzo 快近 5 倍) 或者規模以略低的压缩率实现更好的性能

许多现代操作系统Chrome操作系统、Android 和各种 Linux 发行版(鲁本图Fedora) 已经有默认启用 zram多年来,特别是对于 RAM 较少的系统。Windows 10苹果系统也可以使用类似的页面文件压缩默认技术

启用 zram 后,您仍然需要一个小的交换分区或交换文件来休眠,但几乎不会对其进行写入。但您必须确保它的优先级低于 zram。如果您使用的是 Ubuntu,只需运行即可sudo apt-get install zram-config。还有蘇達缓存。我还没有尝试过,但可能值得一试

进一步阅读

相关内容