- Android系統級深入開發
- 韓超 梁泉
- 1137字
- 2018-12-29 13:39:32
4.3.1 wakelock和earlysuspend
wakelock是Android提供的一種特殊的機制,用于請求CPU資源。當持有wakelock之后,可以阻止系統進入暫停或其他低功耗狀態。
wakelock和earlysuspend的頭文件在include/linux/目錄中,實現的內容在kernel/power/目錄中,其Makefile組織如下所示:
obj-$(CONFIG_FREEZER) += process.o obj-$(CONFIG_WAKELOCK) += wakelock.o obj-$(CONFIG_USER_WAKELOCK) += userwakelock.o obj-$(CONFIG_EARLYSUSPEND) += earlysuspend.o obj-$(CONFIG_CONSOLE_EARLYSUSPEND) += consoleearlysuspend.o obj-$(CONFIG_FB_EARLYSUSPEND) += fbearlysuspend.o
wakelock.c是wakelock的核心實現。userwakelock.c是在用戶空間使用wakelock的接口實現。earlysuspend.c是earlysuspend機制的核心實現。consoleearlysuspend.c和fbearlysuspend.c是console和framebuffer在處理earlysuspend時的具體實現。
wakelock的接口定義的常量在wakelock.h中,內容如下所示:
enum { WAKE_LOCK_SUSPEND, /* 阻止掛起 */ WAKE_LOCK_IDLE, /* 阻止低能耗的Idel */ WAKE_LOCK_TYPE_COUNT };
該枚舉定義了wakelock的種類。WAKE_LOCK_SUSPEND用于阻止系統進入suspend狀態(CPU掛起),一般是深度休眠,Android提供了通用實現。WAKE_LOCK_IDLE用于阻止系統進入idle狀態(CPU低功耗運轉),一般在需要比較多的計算資源時候,申請此wakelock,各家芯片商對該wakelock的底層實現可以不一樣。
wakelock的接口如下所示:
void wake_lock_init(struct wake_lock *lock, int type, const char *name); void wake_lock_destroy(struct wake_lock *lock); void wake_lock(struct wake_lock *lock); void wake_lock_timeout(struct wake_lock *lock, long timeout); void wake_unlock(struct wake_lock *lock);
wake_lock_init對應wake_lock_destroy。用于創建和銷毀一個wakelock。wake_lock和wake_unlock對應,用于持有和釋放一個wakelock。wake_unlock持有一個帶超時機制的wake_lock,會在超時后自動unlock。
以上接口主要用于內核空間驅動程序等使用。很多驅動程序使用wakelock來阻止CPU進入休眠,以完成關鍵傳輸。
在用戶空間中,可以通過userwakelock.c中基于此實現的接口來調用。wakelock在用戶空間的接口為Sys文件系統的/sys/power/wake_lock和/sys/power/wake_unlock。通過對其的寫入,讀出操作,完成持有,釋放等操作。
Android系統電源管理功能,通過這里的接口,把wakelock暴露給用戶空間的應用程序。
wakelock機制與earlysuspend(早期掛起)結合,形成Android獨有的電源管理機制。后者通過在linux標準的suspend前,resume后這兩個環節分別插入earlysuspend,lateresume來實現。
earlysuspend其實是一個完全掛起前中間狀態。簡單的來說,該狀態下,屏幕和背光關閉,不響應諸如傳感器和觸摸屏的事件。該狀態對于移動設備來說是非常常見的,比如關閉屏幕播放音樂等。而標準Linux中并沒有該狀態,因此Android進行了擴充。
擴充earlysuspend以后,原有的掛起操作(例如:在用戶空間向/sys/power/state中寫入“mem”的操作),并不直接將kernel掛起。而是進入earlysuspend,直到最后一個wakelock被釋放,再進入原kernel的掛起流程。
例如,應用上述機制,音樂播放的模式就比較容易實現。只需要一直持有wakelock,即可停留在earlysuspend模式,屏幕背光可以被關閉實現省電,而CPU被占有繼續進行播放工作。
earlysuspend主要提供了如下的接口:
struct early_suspend { #ifdef CONFIG_HAS_EARLYSUSPEND struct list_head link; int level; void (*suspend)(struct early_suspend *h); void (*resume)(struct early_suspend *h); #endif }; #ifdef CONFIG_HAS_EARLYSUSPEND void register_early_suspend(struct early_suspend *handler); void unregister_early_suspend(struct early_suspend *handler); #else #define register_early_suspend(handler) do { } while (0) #define unregister_early_suspend(handler) do { } while (0) #endif
以上函數用于各驅動程序實現并注冊各自的發生early_suspend和late_resume時候的處理功能。
consoleearlysuspend和fbearlysuspend實現了console和framebuffer處理early_suspend和late_resume時的處理函數。并暴露了用戶空間接口,以和Android系統框架進行交互,判斷是否需要繼續繪制屏幕。
提示:在編寫傳感器、觸摸屏、背光等設備驅動程序時,為了能源管理的處理,可以先注冊相應的early_suspend和late_resume處理函數。
從實現上來看,Android的wakelock和earlysuspend機制,在一定程度上改變了Linux原有的電源管理機制。同時,將強制占有CPU而不允許掛起的能力賦予應用程序,有可能對省電管理問題造成混亂。
- 多媒體CAI課件設計與制作導論(第二版)
- Hands-On Machine Learning with scikit:learn and Scientific Python Toolkits
- PostgreSQL Cookbook
- 程序員面試算法寶典
- 基于Java技術的Web應用開發
- 程序員考試案例梳理、真題透解與強化訓練
- Java游戲服務器架構實戰
- HTML5+CSS3網站設計教程
- Python機器學習:手把手教你掌握150個精彩案例(微課視頻版)
- Building a Quadcopter with Arduino
- Python編程與幾何圖形
- Go語言編程
- JavaScript程序設計(第2版)
- Python編程基礎教程
- Python滲透測試編程技術:方法與實踐(第2版)