linux 电源管理 12,Linux电源管理(12)_Hibernate功能

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的状态大致如下图:

7d36fd96111b2c2196fd73464daae2fb.png

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。

(全文完)

如上流程图:

c6a6308114f401be7df747ae46f2b4db.png

评论:

大衍真君

2020-04-15 10:16

@wowo

1、对于hibernate功能的实现像是纯软件实现的,不依赖特定的硬件平台,但是为何默认都不支持此功能(移动设备,比如手机)?

2、hibernate中模式:reboot,platform和shutdown,对于platform跟shutdown有什么区别呢

2019-11-01 21:08

是否可以分析一下STDisk的性能如何,在移动设备实现STD是否有必要

Rafe

2018-03-27 14:17

Hi Physh, Wowo,

请教个问题:我现在用的高通的平台,想要实现suspend to disk的功能,可是在内核中没有发现save_processor_state(),swsusp_arch_suspend()的实现,感觉是被裁剪了......或者我没找到.....

请问Physh分析Hibernate流程中的实现路径在哪里?另外,如何确定内核本身是否有实现这个功能?

Thanks~~

2016-03-15 15:26

你好,我想问下, 您在 内容B. Swap 接口 里面画的图 里面的1,2,3 bitmap metadata 是指之前提到的copy_bm和orig_bm 吗,还是copy_bm和orig_bm这两个bitmap 会在snapshot image 里面

2017-10-25 17:15

@HelloYBSZ:如果没记错的话,bitmap metadata存放就是orig_bm, 具体有些不记得了~copy_bm和orig_bm不会放到snapshot image里边去。

2016-02-25 17:47

你好,请问下在TuxOnice中 为什么要设置两个PageSet 。官方说是如不用两个PageSet  就只能保存一半内存的镜像大小。这是为什么呢?

2016-02-25 19:01

@HelloYBSZ:帮你找了一个链接(d. Write the first part of the image.):

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

还有一个问题,Linux休眠时候,系统休眠的数据是保存到swap分区的。能否保存到其他地方的,比如对于持久化内存,这些数据能否保存到持久化内存里面?

2015-12-30 21:27

@HelloYBSZ:是不是可以在保存到swap分区之后,dd到其它分区中?

2015-12-30 21:54

@wowo:恩,我想问下,不能跨过swap分区,直接保存到其他分区?

2015-12-30 22:14

@HelloYBSZ:应该可以,你可以看看写swap的代码,变成写分区的就可以了。

2015-12-31 11:54

@wowo:请问博主了解做全系统状态保存的开源项目吗,目前一头雾水,我想看下别人怎么做的,学习下。

2015-12-31 11:55

@HelloYBSZ:或者热启动的实现,特别是保存数据和恢复状态这一块

2017-10-25 17:16

@HelloYBSZ:可以把持久化内存直接挂成swap分区呀

2015-12-30 09:57

你好,我想问下如何实现热启动,特别是内存数据,CPU数据,寄存器数据的保存和恢复这一块

2015-05-14 21:19

LZ写的太好了  受益匪浅,尤其是画的图

zr

2015-01-12 23:04

请问Hibernation.pdf和Resume Flowchart.pdf 是用什么工具画出来的?很好看

2015-01-16 10:04

@zr:就是流程图软件啊

wowo

2014-12-22 18:22

文章写的非常不错,特别是附件的流程图,把整个Hibernate的过程,讲的很清楚。谢谢分享。

有两个小建议:

1. 编辑文章时,在下面部分可以添加摘要信息,那样首页就不会出现整篇文章。

2. 我之前写过一些电源管理子系统的文章(http://www.wowotech.net/sort/pm_subsystem),其中STR、autosleep、wakelocks等都有介绍,但hibernate功能一直没写,不知您能否把这篇文章补充进去?例如Linux电源管理(12)_Hibernate功能。

非常感谢!!

wowo

2014-12-22 18:28

@wowo:另外后台有有一个“文章链接别名”的功能,可以给文章链接起个别名,例如现在的链接是:http://www.wowotech.net/linux_kenrel/127.html,通过别名(如”hibernate“),可以修改为:http://www.wowotech.net/linux_kenrel/hibernate.html。

这样的会丰富一点。

2014-12-25 11:06

@wowo:我好像没有启用连接别名的权限哦,是否需要蜗蜗开启权限呢?

wowo

2014-12-25 12:22

@Physh:不用的,你看到的那个提示,只是一个提示。只要是作者都有权限。

2014-12-25 10:58

@wowo:嗯,谢谢肯定,我加进去

发表评论:

昵称

邮件地址 (选填)

个人主页 (选填)

d4e3789769c8ad44c7e403863bfc3822.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值