随着智能手机的普及,大家对手机续航也越来越重视,而手机处于休眠状态又是手机最省电的一种模式,因此本文简单介绍下android下suspend的流程。

一、用户空间发起suspend流程

我们知道内核提供了文件节点 /sys/power/state 给用户空间,用来设置当前系统要处于的状态(s2idle/s2ram/std),本文主要介绍s2ram,我们先查看与这个文件相关的进程:

发现是android.system.suspend@1.0-service这个进程在打开这个文件,查看这个进程相关的代码,可以看到autosuspend的流程:

图 1 autosuspend流程

  • Sleep 100ms(初始值)。

  • 读取/sys/power/wakeup_count的值,读取不到返回第一步;读到的值这里暂以count_r来代替。

  • 把count_r写入/sys/power/wakeup_count文件节点,写入成功,则写“mem”到/sys/power/state节点;写入失败,增加sleep时间(maxsleeptime:2min),转到1。

从上面的流程能看到wakeup_count很重要,读取不到wakeup_count及写入wakeup_count失败,都会导致本次的suspend流程失败。

1、wakeup_count的由来

想想如果没有wakeup_count,这时系统马上就要进入suspend,但一个event已经通知到了用户空间,还没来得及执行后续的动作,那这个event只能等待下个wakeup event唤醒系统才有机会执行了。因此,wakeup_count存在的一个根本原因是保证wakeup event执行的原子性(这里与指令操作的原子性有区别)。

wakeup_count是怎样影响suspend流程的呢?

先看下kernel里面wakeup_count的存在形式:

回到autosuspend的流程,当在读取wakeup_count的时候,如果有正处于active状态的wakeup event时, autosuspend进程会在此阻塞(能走到suspend流程说明系统也确实没其它什么事了),直到系统没有了处于active状态的wakeup event或者该进程被中断、信号唤醒才会返回,当返回时如果还有处于active状态的wakeup event,这也标识着读失败,继续循环读取;读取成功后,会把前16bit的值传给autosuspend进程。

读到wakeup_count后,会尝试再往wakeup_count里面写入读到的值,如果这时检测到有处于active状态的wakeup event或者本次读取到的Registered wakeup events与写入的值不相等(表示这期间有wakeup 的events触发过,是有风险的),这时会写入失败,suspend流程被中止。

2、pm_wakeup_pending的作用

检测suspend流程是否能触发,并继续走下去,能看到是内核与用户空间通过wakeup_count这个媒介一起配合完成的(参考pm_save_wakeup_count的实现),而在写入wakeup_count完成后,内核继续在suspend 执行路径里面做这种异常的检测,基本是在suspend路径中比较耗时的动作前后插桩检测,见pm_wakeup_pending的实现,如果我们想要知道在suspend过程中是因为哪些wakeup events的出现导致了流程被中止,在这里可以做下标识。

二、Suspend内核流程跟踪

风险暂时排除后,开始尝试进入suspend流程,通过写入“mem”到state节点(本文只讨论mem的这种情况)。由于suspend内核流程比较复杂,这里只描述比较重要的环节。

如果系统走的是psci的统一接口,suspend_ops只有valid和enter被赋值,其它的成员先暂不介绍。

图 2 suspend_ops示例

1、首先是同步文件系统,见SYSCALL_DEFINE0(sync)的实现,这一步保证suspend前所有写入的数据被同步到块设备,不会丢失,主要是唤醒块设备的pdflush相关进程,然后写脏inode,写块设备,提交缓存数据到journal(ext4),保证在sync这一刻之前的数据不会丢失。

2、准备并冻结进程(suspend_prepare),由以下几步组成:

1) pm_prepare_console给suspend分配一个虚拟终端来输出信息;

2) 发送一个系统要进入suspend的notify。

3) _usermodehelper_disable禁止创建新的usermode helper,内核不再接收这种helper进程的创建。

4) 冻结用户进程及内核进程,及内核相工作队列,唤醒所有的应用进程(fake_signal_wake_up)及内核进程,应用进程的freeze通过信号处理相关函数来调用到try_to_freeze进行冻结,而可冻结的内核进程需要有能力处理冻结流程并显式调用try_to_freeze进行冻结,冻结的最终实现在__refrigerator,每一个被冻结的进程都会调到这来,就像放入冰箱一样,主要也是设置state为TASK_UNINTERRUPTIBLE,然后判断如果要freeze,就调用schedule()把自己切出运行队列。

3、suspend_test这个功能,我们可以用来调试系统在未进入真正的suspend前的某些固定阶段的状态,使能后,借助rtc来做timer发起suspend test主流程,这些固定阶段嵌在suspend流程里,包括以下几个阶段:TEST_FREEZER->TEST_DEVICES-> TEST_PLATFORM->TEST_CPUS->TEST_CORE,由浅入深,当suspend走到你要调试的阶段后,会在这个阶段上睡眠一段时间,供我们来调试系统。

4、休眠设备并进入suspend(suspend_devices_and_enter),由以下步骤组成:

1) 调用platform_suspend_begin,这个区分平台,看下平台是否有在suspend开始时执行操作的需求。略过。

2) suspend console,ptintk将不能打印。

3) suspend所有非系统设备,即调用设备注册的suspend回调(dpm_suspend_start)。device节点的流转过程就是device在整个休眠唤醒过程中的流程,对文字敏感的朋友可以直接看下图。对单个设备来讲,先从dpm_list链表中取出device并执行该 device的prepare回调,成功后会把该device节点移动到dpm_prepared_list链表,后面在做 dpm_suspend时,会从这个链表里面取device,执行suspend的回调,成功后会把该device移动到dpm_suspended_list链表,dpm_suspend_late中会从dpm_suspended_list链表中取出device执行suspend_late回调,然后把device节点移动到dpm_late_early_list链表,dpm_noirq_suspend_devices里会从dpm_late_early_list链表中取出device执行suspend_noirq回调,并把device节点移动到dpm_noirq_list链表,在后续resume过程中dpm_resume_noirq中又会从dpm_noirq_list链表中取出device执行resume_noirq回调,并把device节点移动到dpm_late_early_list链表,dpm_resume_early时会从dpm_late_early_list链表中取出device并执行resume_early回调,然后把device节点链入dpm_suspended_list链表,在dpm_resume时会从dpm_suspended_list链表中拿到device执行resume回调,并把device节点再移动到dpm_prepared_list链表,最后执行dpm_complete时,会从dpm_prepared_list链表中拿到device执行complete回调,并把device重新链入dpm_list链表。完成device节点的流转。设备的休眠和唤醒是系统休眠唤醒的重要组成部分,流转流程如下图:

图 3 设备节点在休眠唤醒流程中流转过程

4) 把系统进入到要求的sleep状态,然后停止运行(suspend_enter)。

三、suspend_enter

单独介绍下suspend_enter,略过一些无感的流程:

1、某些平台需要在这个阶段做一些准备动作,通过调用suspend_ops->prepare来实现平台相关的操作。

2、执行上面已经介绍过的设备的suspend_late回调。

3、dpm_suspend_noirq做的工作是先禁止cpu进入idle,毕竟要进suspend了就不需要再进行idle的选择了,然后开始禁止设备的中断,禁止中断前,会先遍历所有的wakeup source,把对应的中断状态置位IRQD_WAKEUP_STATE flag,这样再禁止中断的过程中轮询到这个中断时,会再加上IRQD_WAKEUP_ARMED flag,没有包含IRQD_WAKEUP_STATE状态的中断会被禁掉。IRQD_WAKEUP_ARMED主要是用来对进入到suspend的wakeup source对应的irq做标识,在irq_may_run里面做快速响应,想想如果在irq_may_run里面返回false代表了什么呢?

4、disable_nonboot_cpus 负责关闭noboot的那些cpu,随后用arch_suspend_disable_irqs关闭bootcpu的中断,即cpu不再响应中断。

5、进入suspend前的最后一步,syscore_suspend主要是执行那些系统及平台在suspend前必需的流程,比如保存一些clk的状态,在resume的时候能恢复clk到suspend前的状态、系统为了对suspend时间的统计及系统时间的更新、也可以用作调试手段,来收集suspend前后的相关信息。

6、最后一步,进入suspend,每种类型的平台实现不同。一般是把主时钟停掉,会启用一个频率更低的时钟来减少功耗,cpu停止运行。

参考文献:

kernel-4.14/Documentation/power/freezing-of-tasks.txt

http://www.wowotech.net/linux_kenrel/suspend_and_resume.html

扫码关注
“内核工匠”微信公众号
Linux 内核黑科技 | 技术文章 | 精选教程

Suspend流程介绍相关推荐

  1. 聊天机器人之需求分析和流程介绍

    聊天机器人之需求分析和流程介绍 1. 需求分析 在黑马头条的小智同学板块实现聊天机器人,能够起到智能客服的效果,能够为使用app的用户解决基础的问题,而不用额外的人力. 但是由于语料的限制,所以这里使 ...

  2. 微信小程序开发的完整流程介绍,新手必读

    自从跳一跳小程序游戏出现后,一夜之间,小程序就变得家喻户晓了,功能开发也越来越丰富,在微信搜一搜就会发现许多大品牌早已有自己的小程序了,越来越多的企业和商家都看中了这个风口,想快速开发出一款属于自己的 ...

  3. sqlyog设置自动补全_sqlyog智能提示如何设置?sqlyog智能提示设置流程介绍

    sqlyog智能提示如何设置?sqlyog智能提示设置流程介绍 更新时间:2019-08-12 作者:cc 最近不少朋友表示还不会设置sqlyog智能提示,使用下面小编就带来sqlyog智能提示设置的 ...

  4. Industry AI Live | 行为动作定位的算法流程介绍与分享

    「Industry AI Live」是 biendata 与人工智能媒体 PaperWeekly 共同发起的学术直播栏目,旨在帮助更多的青年学者宣传其最新科研成果.我们一直认为,单向地输出知识并不是一 ...

  5. ARKit从入门到精通(2)-ARKit工作原理及流程介绍

    转载请注明出处:ARKit从入门到精通(2)-ARKit工作原理及流程介绍 1.1-写在前面的话 1.2-ARKit与SceneKit的关系 1.3-ARKit工作原理 1.3.1-ARSCNView ...

  6. 对于SAP的月结相关流程介绍

    对于SAP的月结相关流程介绍 流程描述 FI期末结帐流程包括应收帐款.应付帐款.固定资产.管理会计结帐.总帐结帐等一系列结帐过程,对于年结增加了余额结转及固定资产年度改变等动作,通过月结及年结处理,出 ...

  7. (2)FPGA开发流程介绍(第1天)

    (2)FPGA开发流程介绍(第1天) 1 文章目录 1)文章目录 2)FPGA初级课程介绍 3)FPGA初级课程架构 4)FPGA开发流程介绍(第1天) 5)技术交流 6)参考资料 2 FPGA初级课 ...

  8. 中兴bsc服务器是什么,中兴BSC内部信令流程介绍

    中兴BSC内部信令流程介绍 中兴BSC内部信令流程介绍(BSC V2版本) 发布人:网络部_许治远 发表时间:2008-11-15 得分:0.50 归属团队:交换维护中心 分类:交换类 来源:独立原创 ...

  9. 死亡搁浅运送系统服务器,死亡搁浅订单23寻物系统服务器流程介绍-死亡搁浅订单23寻物系统服务器怎么做_牛游戏网...

    在<死亡搁浅>这款送快递游戏中,我们会接到各种难易不同的订单,可能很多玩家对于要怎么完成这些订单不是很了解,所以小编这次就为大家带来了<死亡搁浅>订单23.寻物:系统服务器流程 ...

最新文章

  1. 25页PPT带你吃透微信、陌陌等著名IM软件设计架构(值得珍藏)
  2. python extended,python list中的append 与 extended 的区别
  3. [凡文]Docker+Jenkins+Gradle+GitLab在Linux服务端自动化构建Android包
  4. 区块链网络安全平台HAPI获Genesis Block Ventures投资
  5. 锂离子电池性能测试软件,锂离子电池的常规性能测试方式介绍
  6. 位图图像和矢量图形的区别
  7. LayoutInflater的使用
  8. 计算机专业买什么牌子的笔记本,买笔记本电脑什么牌子好(2020年6月笔记本电脑推荐)...
  9. 剧本创作时的标准格式,让你的剧本轻松得到制片公司青睐
  10. DirextX7。0 SDK 在VC 6.0 环境中使用的注意事项
  11. IIS 配置网站出现500内部服务器错误,显示具体错误信息
  12. 大数据学习计划(不断改善)(小白入门指南)
  13. 北京办理互联网经营许可证(ICP证)的要求
  14. 赴美工作常识(Part 6 - 绿卡排队)
  15. 项目:机器学习+FLD分类+python图像处理mnist数据集
  16. 【Leetcode】周赛204 罗布乐思
  17. 影评分析第2篇 《博人传-火影忍者新时代》透过2W条评论看动漫
  18. Redis高可用——主从复制、哨兵模式、集群
  19. 文本编辑工具 | Editplus_v5.5 +汉化包,用于java、C/C++的语言工具
  20. 在 JavaScript 中对数组进行 for-each

热门文章

  1. 自定义view 太极八卦图
  2. dc-3 靶机渗透学习
  3. 逃离塔科夫最新无挂服务器,逃离塔科夫离线版服务端
  4. 数据结构-单链表基本操作(C语言实现)
  5. Zjh游戏(二十)单机左右玩家下注
  6. LBP算法(人脸识别特征提取)
  7. java jaxb_JavaEE学习之JAXB
  8. eclipse 导入工程中文出现�问号乱码(默认UTF-8也没用)
  9. 作业三:高温预警系统项目中的观察者模式解析
  10. 【转】下载太慢?简单设置让iTunes提速十几倍