用户空间软件挂起接口文档¶
2006 Rafael J. Wysocki <rjw@sisk.pl>
首先,交换挂起 开头的警告仍然适用。
其次,如果您还没有阅读过 交换挂起 中的 FAQ,请_立即_阅读。
现在,要使用用户空间接口进行软件挂起,您需要特殊的实用程序,这些实用程序将从/向内核读取/写入系统内存快照。例如,这些实用程序可从 <http://suspend.sourceforge.net> 获取。如果您打算开发自己的挂起/恢复实用程序,您可能需要查看一下它们。
该接口由一个字符设备组成,该字符设备提供 open()、release()、read() 和 write() 操作以及 include/linux/suspend_ioctls.h 中定义的几个 ioctl() 命令。该设备的主设备号和次设备号分别为 10 和 231,它们可以从 /sys/class/misc/snapshot/dev 中读取。
该设备可以打开以进行读取或写入。如果打开用于读取,则认为处于挂起模式。否则,假定为处于恢复模式。该设备不能同时打开用于读取和写入。同时也不可能一次打开该设备多次。
即使打开设备也会产生副作用。数据结构被分配,并且会调用 PM_HIBERNATION_PREPARE / PM_RESTORE_PREPARE 链。
设备识别的 ioctl() 命令是
- SNAPSHOT_FREEZE
冻结用户空间进程(当前进程不会被冻结);这是 SNAPSHOT_CREATE_IMAGE 和 SNAPSHOT_ATOMIC_RESTORE 成功所必需的
- SNAPSHOT_UNFREEZE
解冻被 SNAPSHOT_FREEZE 冻结的用户空间进程
- SNAPSHOT_CREATE_IMAGE
创建系统内存的快照;ioctl() 的最后一个参数应该是指向 int 变量的指针,该变量的值将指示调用是否在创建快照后返回 (1) 或在从中恢复系统内存状态后返回 (0) (恢复后,系统再次发现自己正在完成 SNAPSHOT_CREATE_IMAGE ioctl());创建快照后,可以使用 read() 操作将其从内核中传输出来
- SNAPSHOT_ATOMIC_RESTORE
从上传的快照映像中恢复系统内存状态;在调用它之前,您应该使用 write() 操作将系统内存快照传输回内核;如果内核无法使用快照映像,则此调用将不会成功
- SNAPSHOT_FREE
释放为快照映像分配的内存
- SNAPSHOT_PREF_IMAGE_SIZE
设置映像的首选最大大小(内核将尽力确保映像大小不超过此数字,但如果事实证明不可能,内核将创建尽可能小的映像)
- SNAPSHOT_GET_IMAGE_SIZE
返回休眠映像的实际大小(最后一个参数应该是指向 loff_t 变量的指针,如果调用成功,该变量将包含结果)
- SNAPSHOT_AVAIL_SWAP_SIZE
以字节为单位返回可用交换空间量(最后一个参数应该是指向 loff_t 变量的指针,如果调用成功,该变量将包含结果)
- SNAPSHOT_ALLOC_SWAP_PAGE
从恢复分区分配一个交换页面(最后一个参数应该是指向 loff_t 变量的指针,如果调用成功,该变量将包含交换页面偏移量)
- SNAPSHOT_FREE_SWAP_PAGES
释放由 SNAPSHOT_ALLOC_SWAP_PAGE 分配的所有交换页面
- SNAPSHOT_SET_SWAP_AREA
设置恢复分区以及从分区开头(以 <PAGE_SIZE> 为单位)偏移量,交换头位于该偏移量处(最后一个 ioctl() 参数应该指向 kernel/power/suspend_ioctls.h 中定义的 struct resume_swap_area,其中包含恢复设备规范和偏移量);对于交换分区,偏移量始终为 0,但对于交换文件,偏移量与 0 不同(有关详细信息,请参阅 将交换文件与软件挂起 (swsusp) 结合使用)。
- SNAPSHOT_PLATFORM_SUPPORT
根据参数值启用/禁用休眠平台支持(如果参数为非零值,则启用)
- SNAPSHOT_POWER_OFF
使内核使用平台(例如 ACPI)驱动程序将系统转换为休眠状态(例如 ACPI S4)
- SNAPSHOT_S2RAM
挂起至 RAM;使用此调用会导致内核立即进入挂起到 RAM 状态,因此必须始终先调用 SNAPSHOT_FREEZE,并且在系统唤醒后还需要使用 SNAPSHOT_UNFREEZE 调用。此调用需要实现挂起到两者机制,其中首先创建挂起映像,就像系统已挂起至磁盘一样,然后将系统挂起到 RAM(这使得可以在电池电量充足时从 RAM 恢复系统,或者在其他情况下根据保存的挂起映像恢复其状态)
设备的 read() 操作可用于将快照映像从内核中传输出来。它具有以下限制
您不能一次 read() 多个虚拟内存页面
不可能跨页边界 read()(即,如果您在上一次调用中 read() 了 1/2 页,则您在下一次调用中将只能 read() **最多** 1/2 页)
设备的 write() 操作用于将系统内存快照上传到内核。它与 read() 操作具有相同的限制。
release() 操作释放为快照映像分配的所有内存以及使用 SNAPSHOT_ALLOC_SWAP_PAGE 分配的所有交换页面(如果有)。因此,在关闭设备之前,无需使用 SNAPSHOT_FREE 或 SNAPSHOT_FREE_SWAP_PAGES(事实上,如果用户空间进程在设备关闭时仍被冻结,它也会解冻被 SNAPSHOT_UNFREEZE 冻结的用户空间进程)。
目前,假定从/向内核读取/写入快照映像的用户空间实用程序将使用交换分区(称为恢复分区)或交换文件作为存储空间(如果使用交换文件,则恢复分区是包含此文件的分区)。然而,这并非真的必需,因为它们可以使用,例如,特殊的(空白)挂起分区或在 SNAPSHOT_CREATE_IMAGE 之前卸载并在之后挂载的分区上的文件。
这些实用程序不得对快照映像中的数据排序做出任何假设。映像的内容完全归内核所有,并且其结构可能会在未来的内核版本中更改。
快照映像必须以未更改的方式写入内核(即,必须以读取的_完全_相同的数量、形式和顺序写入所有映像数据、元数据和标头)。否则,恢复后的系统的行为可能是完全不可预测的。
在执行 SNAPSHOT_ATOMIC_RESTORE 时,内核会检查快照映像的结构是否与存储在映像头中的信息一致。如果检测到任何不一致,SNAPSHOT_ATOMIC_RESTORE 将不会成功。尽管如此,这并非万无一失的机制,并且使用该接口的用户空间实用程序应使用其他手段(如校验和)来确保快照映像的完整性。
挂起和恢复实用程序必须在调用 SNAPSHOT_FREEZE 之前将自己锁定在内存中,最好使用 mlockall()。
挂起实用程序必须检查 SNAPSHOT_CREATE_IMAGE 存储在 ioctl() 的最后一个参数指向的内存位置中的值,并按照该值进行操作
如果值为 1(即,系统内存快照刚刚创建,并且系统已准备好保存它)
除非要取消整个挂起过程,否则挂起实用程序不得关闭快照设备。在这种情况下,如果已经保存了快照映像,则挂起实用程序应该销毁它,最好是清除其标头。如果不是取消挂起,则必须在保存快照映像后关闭系统电源或重新启动系统。
挂起实用程序不应尝试对在调用 SNAPSHOT_CREATE_IMAGE 之前挂载的文件系统执行任何文件系统操作(包括读取)。但是,它可以挂载当时未挂载的文件系统,并在其上执行一些操作(例如,使用它来保存映像)。
如果值为 0(即,系统状态刚刚从快照映像中恢复),则挂起实用程序必须关闭快照设备。之后,它将被视为常规用户空间进程,因此无需退出。
恢复实用程序不应尝试挂载在挂起之前可能挂载的任何文件系统,并且不应尝试执行任何涉及此类文件系统的操作。
有关详细信息,请参阅源代码。