官术网_书友最值得收藏!

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而不允許掛起的能力賦予應用程序,有可能對省電管理問題造成混亂。

主站蜘蛛池模板: 浙江省| 余庆县| 都匀市| 竹山县| 广汉市| 平谷区| 舞钢市| 达州市| 永登县| 高邑县| 军事| 静海县| 陇西县| 大埔区| 温宿县| 香河县| 灵石县| 吉木萨尔县| 介休市| 合作市| 息烽县| 郯城县| 怀仁县| 德庆县| 额尔古纳市| 峨山| 安岳县| 涡阳县| 本溪| 奉节县| 乌拉特前旗| 龙门县| 印江| 海阳市| 惠东县| 中西区| 绥芬河市| 江油市| 尼勒克县| 万州区| 张家川|