Linux电源管理(12)_Hibernate功能
作者:Physh 发布于:2014-12-22 11:51 分类:电源管理子系统
出于省电和快速开机的需求, Hibernation经常被应用到Laptop和移动终端上,本文就简单讲讲Hibernation的一种实现实现方法,SWSUSP( Swap Suspend),其实swsusp从2.6开始就已经被引入到内核版本树中了,所以如果想分析swsusp的代码实现的话,还是挺方便的,只要有有2.6之后的内核代码即可。
本文不会过分深入分析代码,但文章最后会给出hibernation 和 resume的整体流程图。
swsusp是一种STD(Suspend to Disk)/STF(Suspend to Flash)的实现方法,其目的是系统断电之后再次开启时还可以恢复用户现场,从开发的角度切入,为了实现这一目的,系统至少需要保存的关键信息有三类:CPU 状态,Register状态,Memory状态。Swap Suspend中的Swap的含义即指明了该方法如何保存Memory的状态,将Memory保存到Swap分区上,当系统恢复时从Swap分区中读出对应的页面并恢复到Memory中。
那其他两类信息呢?一方面可以另开一块内存空间保留CPU、Register的状态,之后随着Memory一起保存到Swap分区,这种方法之后会讲到,在通过U-boot实现的STF的方法用到了。内核使用了另外一种方法,借用了Kernel CPU Suspend框架,Suspend时让CPU进入Suspend状态,Resume时再从这个状态返回,这样就不同特地去保存CPU、Register状态,不过,话是这样讲,其实本质上还是和第一种方法差不多,CPU Suspend会将Register保存在一个名为sleep_save_sp的指针变量指向的一块预留的内核栈空间中,恢复时从中获取寄存器信息。
从简单入手,思考一下通过U-boot如何试下STF/STD?
要从正常运行的系统跳转到U-boot,可以想到的唯一的办法只有Reset了。那Reset之前需要做什么呢?从U-boot的角度来考虑这个问题吧,如果要通过U-boot来实现这个功能,U-boot就有三种状态,1. 冷启动, 2. 热启动(Restore), 3. 制作内存镜像。
这三种状态肯定需要类似于Flag的东西来区别,所以系统Reset之前需要设置Flag来告知U-boot这次Reset的目的是制作内存镜像;另外,U-boot对当前内存使用情况以及Register状态一无所知,不过这些都还不是大问题,因为一般U-boot事先会知道PAGE_OFFSET,这样就可以通过PAGE_OFFSET得出swap_page_dir以及page_map[],寄存器的状态也可以在进入U-boot之后立即保存下来即可。不过,必须提及的是,Reset必须在所有已经都停止之后做,并且Resume回来的时候所有硬件都必须重新初始化。
通过U-boot实现无可避免就是需要多保存内存,当拿到page_map[]之后,U-boot可以通过各个Page的属性来判断这个页面是否需要保存,当然也可以把整块RAM都保存下来,不过是浪费一点空间。还有一个问题就是U-boot中不能依靠内核Swap机制的接口,所以这些数据往哪儿保存呢?直接往Swap分区写肯定是不行的,因为里边还有系统正常运行时swap out出来页面,要么就要像内核一样有办法获取Swap分区的free block,不行就另想办法,可以往文件里边写,或者弄一个保留分区啥的。
回到正题,Swsusp如何实现STF。
内核对于这个目的的实现就显得比U-boot优雅得多了,与此同时,也复杂的多了,所以说有时粗暴的方法也不见得就是坏办法。swsusp会尝试把最终snapshot image制作的尽可能小,不过这个尺寸用户是可以调控的。
A. Memory Bitmap 机制
看到bitmap估计很多人都会想起内核启动期间用到的boot_mem,这里的所提及的bitmap和boot_mem本质是一样,只是在swsusp中不同的bitmap所代表的作用不一,但方法都是通过bit来代表offset,最终对应到一个Page。
swsusp会扫描zone_list,把不需要保存的page标记起来,这样在制作snapshot image就可以减少image的尺寸。整个过程中用到的bitmap有四张,forbidden_pages_map, free_pages_map, copy_bm, orig_bm,其中不需要保存的page就在forbidden_pages_maps中标记,free_pages_map的作用用于标识当前系统空闲的PAGE,copy_bm标记的是临时保存要写如swap分区中的页面,orig_bm标志系统中所有需要保存的PAGE。
B. Swap 接口
说这个就直接看下面这个图好了,最终往Swap写入之后Swap的状态大致如下图:
C. Kernel Power Manage机制
之前讲过,swsusp中嵌入Kernel PM从而避免了很多电源管理的冗余操作,其实这样做的好处还可以避免花多很功夫去使得各个驱动恢复到Hibernate之前的状态,所以从各个设备的角度去看,可以认为系统进入一个Suspend状态,只是时间有点长,中途还断电了,不过这些设备都不必操心,因为Restore的时候,它们走标准PM Resume流程又回到之前的状态。
D. Swap Header & swap_page_map
在Hibernation的时候,内核会把swap分区的swap_header换掉,换成自己的swap_header,这么做的原因是因为Swap 分区在正常使用过程中是按照内存方式使用的,所以如果是冷启动Swap分区肯定更要重置,因此标准的swap_header没必要记录一些offset什么的,但是restore的时候不一样,拿到Swap分区如何找到snapshot image放在什么地方?这就需要替换的swap_header来提供了,而swap_header在swap分区中的位置是不会变的。
还有一个问题就是,Swap中保存snapshot image的page不一定是连续,因此还得有一个方式来映射,这个工作就由swap_page_map做了,它本质还是一种bitmap,只是保存的不是内存的页面,而是Swap中的Offset。
(全文完)
如上流程图:
标签: Kernel hibernation
评论:
2018-03-27 14:17
请教个问题:我现在用的高通的平台,想要实现suspend to disk的功能,可是在内核中没有发现save_processor_state(),swsusp_arch_suspend()的实现,感觉是被裁剪了......或者我没找到.....
请问Physh分析Hibernate流程中的实现路径在哪里?另外,如何确定内核本身是否有实现这个功能?
Thanks~~
2016-03-15 15:26
2016-02-25 17:47
2016-02-25 19:01
Pageset 2 contains pages on the active and inactive lists; essentially the page cache. Pageset 1 contains all other pages, including the kernel.
http://tuxonice.nigelcunningham.com.au/node/50,按理说TuxOnice就是这样设计的,应该不需要纠结吧。
2015-12-30 21:00
2014-12-22 18:22
有两个小建议:
1. 编辑文章时,在下面部分可以添加摘要信息,那样首页就不会出现整篇文章。
2. 我之前写过一些电源管理子系统的文章(http://www.wowotech.net/sort/pm_subsystem),其中STR、autosleep、wakelocks等都有介绍,但hibernate功能一直没写,不知您能否把这篇文章补充进去?例如Linux电源管理(12)_Hibernate功能。
非常感谢!!
功能
最新评论
- bngvwzdlzj
天上碑仙境RO诛仙服务端出售www.81uv.com9155... - 北葵依旧菜
感谢博主,博主多年前的文章在今天依旧熠熠生辉,解答了很多疑惑 - jqdeng
@新手:curr的确是从rb tree拿下来了,但是on_r... - leelockhey
@入行真的好难:遇到写得好的技术博客真滴少啊,遇到写得好的一... - 飞翔的蜗牛2024
请问怎么在head.S中bl __enable_mmu后使用... - Jam
2024.9.1来考古
文章分类
随机文章
文章存档
- 2024年2月(1)
- 2023年5月(1)
- 2022年10月(1)
- 2022年8月(1)
- 2022年6月(1)
- 2022年5月(1)
- 2022年4月(2)
- 2022年2月(2)
- 2021年12月(1)
- 2021年11月(5)
- 2021年7月(1)
- 2021年6月(1)
- 2021年5月(3)
- 2020年3月(3)
- 2020年2月(2)
- 2020年1月(3)
- 2019年12月(3)
- 2019年5月(4)
- 2019年3月(1)
- 2019年1月(3)
- 2018年12月(2)
- 2018年11月(1)
- 2018年10月(2)
- 2018年8月(1)
- 2018年6月(1)
- 2018年5月(1)
- 2018年4月(7)
- 2018年2月(4)
- 2018年1月(5)
- 2017年12月(2)
- 2017年11月(2)
- 2017年10月(1)
- 2017年9月(5)
- 2017年8月(4)
- 2017年7月(4)
- 2017年6月(3)
- 2017年5月(3)
- 2017年4月(1)
- 2017年3月(8)
- 2017年2月(6)
- 2017年1月(5)
- 2016年12月(6)
- 2016年11月(11)
- 2016年10月(9)
- 2016年9月(6)
- 2016年8月(9)
- 2016年7月(5)
- 2016年6月(8)
- 2016年5月(8)
- 2016年4月(7)
- 2016年3月(5)
- 2016年2月(5)
- 2016年1月(6)
- 2015年12月(6)
- 2015年11月(9)
- 2015年10月(9)
- 2015年9月(4)
- 2015年8月(3)
- 2015年7月(7)
- 2015年6月(3)
- 2015年5月(6)
- 2015年4月(9)
- 2015年3月(9)
- 2015年2月(6)
- 2015年1月(6)
- 2014年12月(17)
- 2014年11月(8)
- 2014年10月(9)
- 2014年9月(7)
- 2014年8月(12)
- 2014年7月(6)
- 2014年6月(6)
- 2014年5月(9)
- 2014年4月(9)
- 2014年3月(7)
- 2014年2月(3)
- 2014年1月(4)
2020-04-15 10:16
1、对于hibernate功能的实现像是纯软件实现的,不依赖特定的硬件平台,但是为何默认都不支持此功能(移动设备,比如手机)?
2、hibernate中模式:reboot,platform和shutdown,对于platform跟shutdown有什么区别呢