大家好,我是极客范的本期栏目编辑小友,现在为大家讲解基于Android的Linux内核的电源管理问题。
1.电源管理的状态。
Android Linux内核为系统提供了四种电源状态。内核的源代码定义了其中三个的名称和相应的宏定义。这些名称在内核/电源/挂起中定义。
[CPP]查看平面图
const char * const PM _ States[PM _ SUSPEND _ MAX]={ 0
# ifdefCONFIG _ EARLYSUSPEND
[PM_SUSPEND_ON]='on ',
#endif
[PM _ SUSPEND _待机]='待机',
[PM_SUSPEND_MEM]='mem ',
};
的宏定义在:include/Linux/suspend . h;
[CPP]查看平面图
typedefinet _ _ bitwisessuspend _ state _ t;
# defineepm _ SUSPEND _ ON(_ _ force SUSPEND _ state _ t)0)
# definePM _ SUSPEND _待机(__forcesuspend_state_t)1)
# defineepm _ SUSPEND _ MEM(_ _ force SUSPEND _ state _ t)3)
# defineepm _ SUSPEND _ MAX(_ _ force SUSPEND _ state _ t)4)
奇怪的是,第四种状态(磁盘)没有具体的定义,而是在代码中硬编码。不知道为什么会这样做,至少我现在看到的版本是这样的(2.6.35)。这就是所谓的挂起到磁盘或休眠。但这不是重点。此外,目前支持hibernate的安卓设备很少。
顾名思义:
PM _ suspend _ on-设备处于全功率状态,即正常工作状态;
PM _ suspend _待机-设备处于省电状态,但也可以接收一些事件,具体行为取决于具体设备;
PM _ suspend _ MEM-暂停到内存,设备进入睡眠,但所有数据仍存储在内存中,只有一些外部中断可以唤醒设备;
目前大多数安卓设备只支持其中的两个:PM_SUSPEND_ON和PM_SUSPEND_MEM,所以下面的讨论是指PM_SUSPEND_MEM。
2.提前暂停、延迟恢复
提前暂停和延迟恢复是基于标准Linux的安卓的附加功能。当用户空间请求内核进入挂起时,会先进入早期挂起状态,驱动可以注册早期挂起的回调函数。当进入这种状态时,内核会逐个调用这些回调函数。例如,显示屏的驱动程序通常会注册早期挂起,在他的回调函数中,驱动程序会关闭屏幕和背光。在这种状态下,所有后台进程都还在活动,应该播放的歌曲和下载的数据还在下载,但是显示画面不好。进入早期挂起状态后,一旦所有唤醒锁被释放,系统将立即进入真正的挂起过程,直到系统停止工作,等待外部事件的唤醒。
图2.1电源状态的转换。
3.安卓电源锁定机制:唤醒锁定。
与标准的Linux内核相比,Android在电源管理上增加了唤醒锁定机制。一旦应用了某一类型的锁定,电源管理模块将“锁定”某一电源状态。目前安卓提供两种锁:
wake _ lock _ suspend-防止系统进入挂起状态;
wake _ lock _ idle-防止系统进入空闲状态;
唤醒锁也可以设置超时,时间到了自动解除锁定。
关于唤醒锁的代码在:kernel/power/wakelock.c。
4.电源状态迁移。
内核启动后,电源管理系统将在sysfs文件系统中创建三个文件:
/sys/power/state
/sys/power/wake_lock
/sys/电源/唤醒_解锁
电源状态的迁移首先由用户空间中的应用程序启动。当系统应用程序检测到某段时间内没有用户活动(如触摸屏、按键)时,可以将相应的电源状态名称写入/sys/power/state文件(请参考第一节)。如果写了“mem”,会触发内核启动挂起进程,内核会按照图2.1迁移状态。应用程序也可以通过/sys/power/wake_lock申请WAKE_LOCK_SUSPEND类型的锁,相应地,可以通过/sys/power/wake_unlock释放锁。如果内核在进入挂起之前检测到锁没有被释放,它将放弃挂起过程,直到锁被释放。