用户空间软件挂起接口文档¶
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() 参数应该指向一个 struct resume_swap_area,如 kernel/power/suspend_ioctls.h 中定义的那样,包含恢复设备规范和偏移量);对于交换分区,偏移量始终为 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 将不会成功。尽管如此,这并不是一个万无一失的机制,使用该接口的用户空间实用程序应该使用额外的手段,例如校验和,来确保快照映像的完整性。
挂起和恢复实用程序必须将自身锁定在内存中,最好使用 mlockall(),然后在调用 SNAPSHOT_FREEZE 之前。
挂起实用程序必须检查 SNAPSHOT_CREATE_IMAGE 存储在 ioctl() 的最后一个参数指向的内存位置中的值,并据此进行操作
如果值为 1(即,系统内存快照刚刚创建,系统已准备好保存它)
_除非_要取消整个挂起过程,否则挂起实用程序不得关闭快照设备,在这种情况下,如果快照映像已经保存,挂起实用程序应该销毁它,最好是通过破坏其标头。如果挂起不取消,则在保存快照映像后必须关闭或重新启动系统。
挂起实用程序不应尝试在调用 SNAPSHOT_CREATE_IMAGE 之前挂载的文件系统上执行任何文件系统操作(包括读取)。但是,它可以挂载当时未挂载的文件系统并在其上执行一些操作(例如,使用它来保存映像)。
如果值为 0(即,系统状态刚刚从快照映像恢复),则挂起实用程序必须关闭快照设备。之后,它将被视为常规用户空间进程,因此不需要退出。
恢复实用程序不应尝试挂载任何在挂起之前可能已挂载的文件系统,并且不应尝试执行任何涉及此类文件系统的操作。
有关详细信息,请参阅源代码。