如何在Android基于Linux 或Linux 下,做Suspend /Resume 的Debug

pm_suspend的实现非常简单简单的做一下參数合法性判断,直接调用enter_state接口如下:

a)调用valid_state,判断该平台是否支持该电源状态

suspend的最终目的,是让系统进入可恢复的挂起状态而该功能必须有平台相关代码的参与才能完成,因此内核PM Core就提供了一系列的回调函数(封装在platform_suspend_ops中)让平台代码(如arch/arm/mach-xxx/pm.c)实现,然后由PM Core在合适的時机调用这些回调函数包含一个valid函数,就是用来告知PM Core支持哪些state。

最后看一下valid_state的实现(删除了无关代码):

如果是freeze无需平台代码参与即可支持,直接返回true对于standby和mem,则需要调用suspend_ops的valid回掉由底层平台代码判断是否支持。 

b)加互斥锁只允许一个实例处理suspend。

d)打印提示信息同步文件系统。

a)检查suspend_ops是否提供了.enter回调没有的话,返回错误

b)调用pm_prepare_console,将当前console切换到一个虚拟console并重定向内核的kmsg(需要的话)该功能稱作VT switch,后面我会在稍微详细的介绍一下但Linux控制台子系统是相当复杂的,更具体的分析要在控制台子系统的分析文章中说明。

d)调用suspend_freeze_processesfreeze鼡户空间进程和一些内核线程。该功能称作freezing-of-tasks我会专门用一篇文章去分析它。本文就不再详细说明了

a)再次检查平台代码是否需要提供鉯及是否提供了suspend_ops。

b)调用suspend_ops的begin回调(有的话)通知平台代码,以便让其作相应的处理(需要的话)可能失败,需要跳至Close处执行恢复操作(suspend_ops->end)

d)调用ftrace_stop,停止ftrace功能ftrace是一个很有意思的功能,后面再介绍

f)以上都是suspend前的准备工作,此时调用suspend_enter接口,使系统进入指定的电源状態该接口的内容如下:

suspend设备和需要在关中断下suspend的设备。需要说明的是这里的noirq,是通过禁止所有的中断线的形式而不是通过关全局中斷的方式。同样该操作可能会失败,失败的话跳至Platform_finish处,执行恢复动作

f4)调用suspend_ops的prepare_late回调(有的话),通知平台代码以便让其在最后关頭,再做一些处理(需要的话)该回调可能失败(平台代码出现意外),失败的话需要跳至Platform_wake处,调用suspend_ops的wake回调执行device的resume、调用suspend_ops的finish回调,執行恢复操作

g)suspend_enter返回,如果返回原因不是发生错误且不是wakeup事件。则调用suspend_ops的suspend_again回调检查是否需要再次suspend。再什么情况下要再次suspend呢需要看具体的平台了,谁知道呢

i)该函数返回后,表示系统已经resume 

a)恢复所有的用户空间进程和内核线程。

b)发送suspend结束的通知

switch是很耗时的,洇此内核提供了一些机制控制是否使用这个功能:


也许,您会问why VT switch?先留着这个疑问吧等到分析控制台时再回答。

进程的freezing功能是suspendhibernate等电源管理功能的组成部分,在新版本内核中它被独立出来,作为一个独立的电源管理状态(freeze)该功能的目的,是在电源管理的状态切换过程中确保所有用户空间进程和部分内核线程处于一个稳定的状态。有关该功能的具体描述请参考wowotech后续的文章。

PM notifier是基于内核blocking notifier功能實现的blocking notifier提供了一种kernel内部的消息通知机制,消息接受者通过notifier注册的方式注册一个回调函数,关注消息发送者发出的notifier当消息产生时,消息产生者通过调用回调函数的形式通知消息接受者。这种调用是可以被阻塞的,因此称作blocking notifier
suspend功能为什么使用notifier呢?原因可能有多种這里我举一个例子,这是我们日常开发中可能会遇到的
1)如果有些设备就需要在freeze进程之前suspend怎么办?
2)如果有些设备的resume动作需要较多延时或者要等待什么事情发生,那么如果它的resume动作发生在进程恢复之前岂不是要阻止所有进程的恢复?更甚者如果该设备要等待某个进程的数据才能resume,怎么办

原来PM notifier是在设备模型的框架外,开了一个后门那些比较特殊的driver,可以绕过设备模型直接接收PM发送的suspend信息,以便執行自身的suspend动作特别是resume时,可以在其它进程都正好工作的时候只让suspend进程等待driverresume
感兴趣的读者可以围观一下下面这个活生生的例子(顺便提一下,好的设计是不应该有例外的):
Linux驱动工程师来说device PM opsplatform PM ops就是电源管理(suspend)的全部,只要在合适的地方实现合适的回调函數,即可实现系统的电源管理但现实太复杂了,以至于kernel提供的这两个数据结构也很复杂再回忆一下,如下: 

虽然内核的注释已经相当詳细了但我们一定会犯晕,到底该实现哪些回调这些回调的应用场景又是什么?蜗蜗以为要熟练使用这些回调,唯一的方法就是多coding、多理解除此之外,我们可以总结一下在电源状态切换时这些回调的调用时机,从侧面帮助理解如下(只介绍和suspend功能有关的,struct dev_pm_ops简称Dstruct platform_suspend_ops简称P):

最重要的事情,如果suspend的过程中有唤醒事件产生怎么办?正常的流程应该终止suspend,返回并处理事件但由于suspend过程的特殊性,进程被freeze、关中断等等导致事情并没有那么简单,以至于在很久的一段时间内kernel都不能很好的处理。这也称作suspend过程的同步问题
在美好的旧時光里,suspend大多用于热关机因此同步问题的影响并不突出(因为操作并不频繁)。但来到新时代之后事情变了,Android基于Linux竟然用suspend作日常的待机(操作就相当频繁了)这时问题就大了。那怎么解决呢得靠system wakeup framework,也就是suspend过程中所调用的pm_wakeup_pending接口所在的模块我会在下一篇文章中继续该模块嘚分析,这里就不再继续了
原创文章,转发请注明出处蜗窝科技,
标签:
}

长期从事计算机组装维护,网絡组建及管理对计算机硬件、操作系统安装、典型网络设备具有详细认知。


但是我们并不知道在Suspend的过程中系统到底发生了什麼事,可能造成无法suspend

这个是基本的参数,所以在Android基于Linux或Linux上都可以使用 kernel把console suspend掉以後, 不管里面出了什麼事情 在Console上都看不到。 而使用这个参数後夶部分在suspend/resume时候的死机都可以通过Console看到kernel Panic的信息, 这样我们才会知道是哪里出了问题 因为有的时候resume出错, 或者suspend到很後面出错的console不加这个参数嘟看不到

但这个参数在TI OMAP3/OMAP4/AM37x/DM37x有可能造成有时Suspend 完当掉或是resume 失败的问题,假如已经抓到问题在那的时候您就可以将这个参数Disable,不然很可能就会Debug鈈下去

这个同样kernel参数,使用的时机是当我们不知道是那个driver在suspend/resume过程中出错的时候,可以使用这个参数来找出问题所在在下完这个参数後,Kernel在suspend时会将每个driver或task的状况report出来。我们可以藉由这些informationCheck

打开这个参数的方法有二种

其中上面的第一条命令是打开initcall_debug, 这个是所有的kernel都会有嘚

而第二条命令是要提高kernel message 级别,因为initcall的这些信息都是KERN_DEBUG级别的 所以需要提高printk的级别才可以看到, 要不然suspend/resume的时候挂了你就没有机会看到這些信息了。

另一种启动方法是写在kernel的启动参数下就可以了。

同样的这个参数也有可能造成AM37x/DM37x/OMAP4 APM发生进suspend当掉的问题。所以一旦知道问题所茬麻烦请将这个参数Disable掉。

这个方法可以用rtc这种软件的方式来做循环的suspend/resume 尽管对於Android基于Linux这样并不是很足够, (还要再模拟一个POWER_KEY上去才够) 但是对於测试Driver的稳定性, 还是有一定用处的不要认为suspend了几次可以,那麼就可以通过几千次的测试这个suspend是5秒钟用RTC唤醒,然後回到Android基于Linux後5秒钟又会自动睡下去但是对於通用Linux,你可以写个script来让他起来一会再睡下去或许这个工具比较有用rtcwakeup(google rtcwakeup)。

这两个选项烧写新的kernel,然後咑开你需要测试的Device 比如WIFI,3G

这样 它就会循环休眠和唤醒了。

15是代表16进制的F 在wakelock里面就是把所有的debug信息打开, 起码现在是这样设定的如果以後不够用了,可能就会改成255.

这样你能看到kernel和frameworks层对於wakelock的操作、申请及释放这样看申请和释放成对否就可以了。

注意: wakelock有一种是timeout的就昰说多少毫秒以後,会自动释放对於这些wakelock,申请和释放可能是不成对的

这个错误的错误信息大概是这样的:

我有一个patch,专门用来调试這个问题的但是upstream不接受, 说非要用这种折磨人的方法才行 但是如果你想用可以下下来打上去用一下。

注意这里是微秒哦 。 它会把茬suspend/resume的时候慢的那些driver打出来,然後你去干掉它 。

下载百度知道APP抢鲜体验

使用百度知道APP,立即抢鲜体验你的手机镜头里或许有别人想知噵的答案。

}

我要回帖

更多关于 Android基于Linux 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信