交换挂起¶
首先,一些警告。
警告
重大警告
- 如果在挂起和恢复之间触碰磁盘上的任何内容...
...就和你的数据说再见吧。
- 如果你在文件系统挂载后从 initrd 恢复...
...再见,根分区。
[这实际上和上面的情况相同]
如果你的 DMA 设备不受支持 ( ),你可能会遇到一些问题。如果你的磁盘驱动程序不支持挂起...(IDE 支持),它也可能导致一些问题。如果在挂起和恢复之间更改内核命令行,它可能会做一些错误的事情。如果系统挂起时更改硬件...嗯,这不是个好主意;但它可能只会崩溃。
( ) 需要挂起/恢复支持才能使其安全。
如果你的 USB 设备上在软件挂起之前挂载了任何文件系统,则在恢复后它们将无法访问,并且你可能会丢失数据,就像你拔掉了挂载了文件系统的 USB 设备一样;有关详细信息,请参阅下面的常见问题解答。(对于像“待机”这样的更传统的电源状态,这并不适用,因为它们通常不会关闭 USB。)
- 交换分区
你需要将 resume=/dev/your_swap_partition 添加到内核命令行,或者使用 /sys/power/resume 指定它。
- 交换文件
如果使用交换文件,你也可以在内核命令行上使用 resume_offset=<数字> 来指定恢复偏移量,或者在 /sys/power/resume_offset 中指定它。
准备好后,你可以通过以下方式挂起:
echo shutdown > /sys/power/disk; echo disk > /sys/power/state
如果你觉得 ACPI 在你的系统上运行良好,你可以尝试
echo platform > /sys/power/disk; echo disk > /sys/power/state
如果你想将休眠映像写入交换空间,然后挂起到 RAM(前提是你的平台支持),你可以尝试
echo suspend > /sys/power/disk; echo disk > /sys/power/state
如果你有 SATA 磁盘,你需要具有 SATA 挂起支持的最新内核。为了使挂起和恢复工作,请确保你的磁盘驱动程序已构建到内核中,而不是作为模块。[有一种方法可以使用模块化的磁盘驱动程序进行挂起/恢复,请参阅常见问题解答,但你可能不应该这样做。]
如果你想将挂起映像大小限制为 N 字节,请执行
echo N > /sys/power/image_size
在挂起之前(默认情况下,它限制为可用 RAM 的 2/5 左右)。
恢复过程会检查是否存在恢复设备,如果找到,则检查内容中是否存在休眠映像签名。如果都找到,则恢复休眠映像。
恢复过程可以通过两种方式触发:
在 lateinit 期间:如果在内核命令行上指定了 resume=/dev/your_swap_partition,则 lateinit 将运行恢复过程。如果尚未探测到恢复设备,则恢复过程将失败,并且启动将继续。
手动从 initrd 或 initramfs:可以使用 /sys/power/resume 文件从 init 脚本运行。至关重要的是,这必须在重新挂载任何文件系统(即使是只读)之前完成,否则数据可能会损坏。
关于 Linux 软件挂起的目标和实现的文章¶
作者:Gábor Kuti 最后修订:2003-10-20,Pavel Machek
要实现的想法和目标¶
如今,许多笔记本电脑都有一个挂起按钮是很常见的。它将机器的状态保存到文件系统或分区,然后切换到待机模式。稍后恢复机器时,保存的状态将加载回内存,机器可以继续工作。它有两个真正的好处。首先,我们节省了机器关闭然后再启动的时间,从电池运行时,能源成本确实很高。另一个好处是,我们不必中断我们的程序,因此长时间计算某些内容的进程不需要被写成可中断的。
swsusp 将机器的状态保存到活动的交换空间,然后重新启动或关闭电源。你必须使用 resume= 内核选项显式指定要从中恢复的交换分区。如果找到签名,它将加载并恢复保存的状态。如果将 noresume 选项指定为启动参数,则它将跳过恢复。如果将 hibernate=nocompress 选项指定为启动参数,则它将保存未压缩的休眠映像。
在系统挂起期间,你不应该添加/删除任何硬件、写入文件系统等。
睡眠状态摘要¶
你可以使用三个不同的接口,/proc/acpi 应该像这样工作:
在一个真正完美的世界里
echo 1 > /proc/acpi/sleep # for standby
echo 2 > /proc/acpi/sleep # for suspend to ram
echo 3 > /proc/acpi/sleep # for suspend to ram, but with more power
# conservative
echo 4 > /proc/acpi/sleep # for suspend to disk
echo 5 > /proc/acpi/sleep # for shutdown unfriendly the system
也许
echo 4b > /proc/acpi/sleep # for suspend to disk via s4bios
常见问题解答¶
- 问
嗯,我认为挂起服务器是一件非常愚蠢的事情,但是... (Diego Zuccato)
- 答
你为服务器购买了新的 UPS。如何在不关闭机器的情况下安装它?挂起至磁盘,重新排列电源线,恢复。
你的服务器在 UPS 上。电源断了,UPS 显示还有 30 秒就失效了。你该怎么办?挂起至磁盘。
- 问
也许我遗漏了一些东西,但为什么常规的 I/O 路径不起作用呢?
- 答
我们确实使用了常规的 I/O 路径。但是,我们无法在加载数据时将其恢复到原始位置。这将创建一个不一致的内核状态,这肯定会导致 oops。相反,我们将映像加载到未使用的内存中,然后原子地将其复制回其原始位置。当然,这意味着最大映像大小为内存量的一半。
对此有两种解决方案:
要求在挂起期间有一半的内存可用。这样你就可以将“新”数据读取到空闲位置,然后 cli 并复制。
假设我们有特殊的“轮询” ide 驱动程序,它只使用 0-640KB 之间的内存。这样,我必须确保在挂起期间 0-640KB 是空闲的,但否则它会工作...。
suspend2 共享此基本限制,但不会将用户数据和磁盘缓存包含在“已用内存”中,因为它会预先保存它们。这意味着该限制实际上会消失。
- 问
Linux 支持 ACPI S4 吗?
- 答
是的。这就是 echo platform > /sys/power/disk 的作用。
- 问
什么是“suspend2”?
- 答
suspend2 是“软件挂起 2”,它是挂起至磁盘的派生实现,可从 swsusp.sourceforge.net 获得适用于 2.4 和 2.6 内核的单独补丁。它包括对 SMP、4GB 高内存和抢占的支持。它还具有可扩展的架构,允许对映像进行任意转换(压缩、加密)和用于写入映像的任意后端(例如,交换或 NFS 共享 [正在进行中])。有关 suspend2 的问题应发送到可通过 suspend2 网站获得的邮件列表,而不是 Linux 内核邮件列表。我们正在努力将 suspend2 合并到主线内核中。
- 问
什么是冻结任务,我们为什么要使用它?
- 答
冻结任务是一种机制,通过该机制,在休眠或系统范围挂起(在某些架构上)期间控制用户空间进程和某些内核线程。有关详细信息,请参阅 冻结任务。
- 问
“platform”和“shutdown”之间有什么区别?
- 答
- shutdown
在 Linux 中保存状态,然后告诉 bios 关闭电源
- platform
在 Linux 中保存状态,然后告诉 bios 关闭电源并闪烁“挂起 LED”
“platform”实际上是在支持的地方正确的事情,但“shutdown”是最可靠的(ACPI 系统除外)。
- 问
我不明白为什么你对选择性挂起的想法有如此强烈的反对意见。
- 答
在运行时电源管理期间进行选择性挂起,这没问题。但它对于挂起至磁盘是无用的。(而且我看不出如何将其用于挂起至内存,我希望你不要那样做)。
让我们看看,所以你建议:
挂起除交换设备及其父设备以外的所有设备
快照
将映像写入磁盘
挂起交换设备及其父设备
关闭电源
哦,不,这不起作用,如果交换设备或其父设备使用 DMA,你已经损坏了数据。你必须这样做:
挂起除交换设备及其父设备以外的所有设备
冻结交换设备及其父设备
快照
解冻交换设备及其父设备
写入
挂起交换设备及其父设备
这意味着你仍然需要那个冻结状态,并且你会得到更复杂的代码。(而且我还没有介绍诸如系统设备之类的细节)。
- 问
在挂起和冻结之间似乎没有任何普遍有用的行为区别。
- 答
当要求你执行冻结时执行挂起总是正确的,但它可能会不必要地慢。如果你希望你的驱动程序保持简单,那么速度可能对你来说无关紧要。它可以稍后修复。
对于像磁盘这样的设备,这确实很重要,你不想为了冻结而停止旋转。
- 问
恢复后,系统分页非常严重,导致交互性非常差。
- 答
尝试运行
cat /proc/[0-9]*/maps | grep / | sed 's:.* /:/:' | sort -u | while read file do test -f "$file" && cat "$file" > /dev/null done
在恢复后。swapoff -a; swapon -a 也可能有用。
- 问
在 swsusp 期间设备会发生什么?它们似乎在系统挂起期间恢复了?
- 答
没错。如果我们想将映像写入磁盘,则需要恢复它们。整个序列如下:
挂起部分
运行系统,用户请求挂起至磁盘
用户进程停止
suspend(PMSG_FREEZE):设备被冻结,以便它们不会干扰状态快照
状态快照:在禁用中断的情况下拍摄整个已用内存的副本
resume():设备被唤醒,以便我们可以将映像写入交换空间
将映像写入交换空间
suspend(PMSG_SUSPEND):挂起设备,以便我们可以关闭电源
关闭电源
恢复部分
(实际上非常相似)
运行系统,用户请求挂起至磁盘
用户进程停止(在通常情况下没有,但是对于从 initrd 恢复,没人知道)
从磁盘读取映像
suspend(PMSG_FREEZE):设备被冻结,以便它们不会干扰映像恢复
映像恢复:使用映像重写内存
resume():设备被唤醒,以便系统可以继续
解冻所有用户进程
- 问
“加密挂起映像”是做什么用的?
- 答
首先:它不能替代 dm-crypt 加密交换。它无法在计算机挂起时保护你的计算机。相反,它可以防止在从挂起恢复后泄露敏感数据。
请考虑以下情况:当一个应用程序正在运行时,你进行了挂起操作,该应用程序将敏感数据保存在内存中。应用程序本身会阻止数据被交换出去。然而,挂起操作必须将这些数据写入交换空间才能在稍后恢复。如果没有挂起加密,你的敏感数据就会以明文形式存储在磁盘上。这意味着在恢复后,所有可以直接访问用于挂起的交换设备的应用程序都可以访问你的敏感数据。如果你在恢复后不需要交换空间,这些数据几乎可以永久保留在磁盘上。因此,可能会出现这样的情况:你的系统在几周后被攻破,而你认为已加密和保护的敏感数据却从交换设备中被检索和窃取。为了防止这种情况,你应该使用“加密挂起镜像”。
在挂起期间,会创建一个临时密钥,该密钥用于加密写入磁盘的数据。当在恢复期间,数据被读回内存时,临时密钥会被销毁,这意味着所有在挂起期间写入磁盘的数据都将无法访问,因此它们无法在以后被窃取。你唯一需要注意的是,在常规启动期间,尽早为用于挂起的交换分区调用“mkswap”。这确保了任何来自崩溃的挂起或失败或中止的恢复的临时密钥都会从交换设备中擦除。
一般来说,在系统关闭或挂起时,使用加密的交换空间来保护你的数据。此外,使用加密的挂起镜像来防止敏感数据在恢复后被盗。
- 问
我可以挂起到交换文件吗?
- 答
一般来说,可以。但是,它需要你使用“resume=”和“resume_offset=”内核命令行参数,因此从交换文件恢复无法从 initrd 或 initramfs 镜像启动。有关详细信息,请参阅使用交换文件进行软件挂起 (swsusp)。
- 问
swsusp 支持的最大系统内存大小是多少?
- 答
它应该可以正常使用 highmem。
- 问
swsusp(到磁盘)是否只使用一个交换分区,还是可以使用多个交换分区(将它们聚合到一个逻辑空间中)?
- 答
抱歉,只能使用一个交换分区。
- 问
如果我的应用程序使用大量内存和交换空间(超过系统总内存的一半),那么在应用程序运行时尝试挂起到磁盘是否可能毫无意义?
- 答
不,它应该可以正常工作,只要你的应用程序不使用 mlock()。只需准备足够大的交换分区即可。
- 问
哪些信息对调试挂起到磁盘的问题有用?
- 答
嗯,屏幕上的最后消息总是很有用的。如果出现问题,通常是一些内核驱动程序的问题,因此尝试加载尽可能少的模块会有很大帮助。我还建议人们从控制台挂起,最好在没有运行 X 的情况下。使用 init=/bin/bash 引导,然后 swapon 并手动启动挂起序列通常会奏效。然后,最好尝试使用最新的 vanilla 内核。
- 问
发行版如何发布支持 swsusp 的内核,并带有模块化的磁盘驱动程序(尤其是 SATA)?
- 答
嗯,可以做到,加载驱动程序,然后从 initrd 中回显到 /sys/power/resume 文件。请务必不要挂载任何内容,甚至不要进行只读挂载,否则你将会丢失数据。
- 问
如何让挂起操作更详细?
- 答
如果你想在内核在挂起期间切换到的虚拟终端上看到任何非错误的内核消息,你必须将内核控制台日志级别设置为至少 4 (KERN_WARNING),例如通过执行以下操作:
# save the old loglevel read LOGLEVEL DUMMY < /proc/sys/kernel/printk # set the loglevel so we see the progress bar. # if the level is higher than needed, we leave it alone. if [ $LOGLEVEL -lt 5 ]; then echo 5 > /proc/sys/kernel/printk fi IMG_SZ=0 read IMG_SZ < /sys/power/image_size echo -n disk > /sys/power/state RET=$? # # the logic here is: # if image_size > 0 (without kernel support, IMG_SZ will be zero), # then try again with image_size set to zero. if [ $RET -ne 0 -a $IMG_SZ -ne 0 ]; then # try again with minimal image size echo 0 > /sys/power/image_size echo -n disk > /sys/power/state RET=$? fi # restore previous loglevel echo $LOGLEVEL > /proc/sys/kernel/printk exit $RET
- 问
如果我在 USB 设备上挂载了文件系统并挂起到磁盘,除非文件系统已使用“sync”挂载,否则我可能会丢失数据,这是真的吗?
- 答
是的,这是正确的……如果你断开该设备的连接,你可能会丢失数据。事实上,即使使用“-o sync”,如果你的程序在缓冲区中有尚未写入断开连接的磁盘的信息,或者如果你在设备完成保存你写入的数据之前断开连接,你仍然可能会丢失数据。
软件挂起通常会关闭 USB 控制器的电源,这相当于断开连接到你系统的所有 USB 设备。
你的系统很可能支持其 USB 控制器的低功耗模式,同时系统处于休眠状态,保持连接,使用真正的睡眠模式,如“挂起到 RAM”或“待机”。(不要将“disk”写入 /sys/power/state 文件;写入“standby”或“mem”。)我们还没有看到任何硬件可以通过软件挂起使用这些模式,尽管理论上某些系统可能支持不会断开 USB 连接的“平台”模式。
请记住,拔下包含已挂载文件系统的磁盘驱动器始终是一个坏主意。即使你的系统处于休眠状态也是如此!最安全的方法是在挂起之前卸载可移动媒体(如 USB、Firewire、CompactFlash、MMC、外部 SATA 甚至 IDE 热插拔托架)上的所有文件系统;然后在恢复后重新挂载它们。
有一个解决此问题的方法。有关详细信息,请参阅系统挂起期间的 USB 设备持久性。
- 问
我可以使用 LVM 下的交换分区进行挂起到磁盘吗?
- 答
是的,也不是。你可以成功挂起,但内核将无法自行恢复。你需要一个可以识别恢复情况的 initramfs,激活包含交换卷的逻辑卷(但不触摸任何文件系统!),并最终调用
echo -n "$major:$minor" > /sys/power/resume
其中 $major 和 $minor 分别是交换卷的主设备号和次设备号。
uswsusp 也适用于 LVM。请参阅http://suspend.sourceforge.net/
- 问
我将内核从 2.6.15 升级到 2.6.16。两个内核都是使用类似的配置文件编译的。无论如何,我发现与 2.6.15 相比,在 2.6.16 上挂起到磁盘(和恢复)要慢得多。有什么原因导致这种情况发生,或者我如何加速它吗?
- 答
这是因为挂起镜像的大小现在比 2.6.15 大(通过保存更多数据,我们可以在恢复后获得更快的系统响应速度)。
有一个 /sys/power/image_size 旋钮,用于控制镜像的大小。如果你将其设置为 0(例如,通过 root 身份执行 echo 0 > /sys/power/image_size),则应恢复 2.6.15 的行为。如果仍然太慢,请查看 suspend.sf.net -- 用户空间挂起速度更快,并支持 LZF 压缩以进一步加速。