wake_lock锁机制和device wakeup

本文是我学习时所写,非百分之百原创,望指出错误之处。
参考资料:
(linux)wake_lock机制
linux设备驱动中device_init_wakeup

Android的休眠唤醒主要基于wake_lock机制,只要系统中存在任一有效的wake_lock,系统就不能进入深度休眠,但可以进行设备的浅度休眠操作。wake_lock一般在关闭lcd、tp但系统仍然需要正常运行的情况下使用,比如听歌、传输很大的文件等。

以下为struct wake_lock结构:

enum {  
    WAKE_LOCK_SUSPEND, // 阻止进入深度休眠模式  
    WAKE_LOCK_IDLE,    // 阻止进入空闲模式  
    WAKE_LOCK_TYPE_COUNT  
};
struct wake_lock {  
#ifdef CONFIG_HAS_WAKELOCK  
    struct list_head    link;     // 链表节点  
    int                 flags;    // 标志  
    const char         *name;     // 名称  
    unsigned long       expires;  // 超时时间  
#ifdef CONFIG_WAKELOCK_STAT  
    struct {  
        int             count;         // 使用计数  
        int             expire_count;  // 超时计数  
        int             wakeup_count;  // 唤醒计数  
        ktime_t         total_time;    // 锁使用时间  
        ktime_t         prevent_suspend_time;  // 锁阻止休眠的时间  
        ktime_t         max_time;      // 锁使用时间最长的一次  
        ktime_t         last_time;     // 锁上次操作时间  
    } stat;  
#endif  
#endif  
};

如上图所示,wake_lock按功能分为休眠锁和空闲锁两种类型,用于阻止系统进入深度休眠模式或者空闲模式,wake_lock机制就和锁机制类似,如果某线程拥有了锁,那么设备会被阻止进入到初始化该锁时设置的休眠模式中。以下为内核提供的操作wake_lock的接口:

void wake_lock_init(struct wake_lock *lock, int type, const char *name);
/*函数wake_lock_init,用来初始化一个新锁,参数type表示所类型;参数name表示锁的名字*/
void wake_lock_destroy(struct wake_lock *lock);//该函数用来销毁一个锁
void wake_lock(struct wake_lock *lock);
/*函数wake_lock,该函数用来永久获得一个锁,如果不使用wake_unlock,则这个锁会一直不释放,换句话说就是该设备一直不会休眠*/
void wake_unlock(struct wake_lock *lock);//该函数用来释放一个永久锁
void wake_lock_timeout(struct wake_lock *lock, long timeout);
/*函数wake_lock_timeout,该函数用来获得一个超时锁,在获得锁,经过timeout设置的时间之后,会自动释放该锁*/

device wakeup 功能
在我们的linux设备模型中,所有设备都有两个标志来控制唤醒事件(可使得设备或系统退出低功耗状态)。抽象设备的数据结构struct device中有以下数据结构:

struct dev_pm_info {
	pm_message_t power_state;
	unsigned can_wakeup:1;
	
	#ifdef CONFIG_PM
	unsigned should_wakeup:1;
	pm_message_t prev_state;
	void * saved_state;
	struct device * pm_parent;
	struct list_head entry;
	#endif
};

如上图所示,can_wakeup字段为1时,表示设备可以被唤醒,为0时相反;should_wakeup为1时,表示设备使用唤醒功能,为0时相反。设备驱动为了支持linux的电源管理,有责任调用device_init_wakeup函数来初始化以上两个成员。device_init_wakeup函数原型如下:

 /* include/linux/pm_wakeup.h */
static inline int device_init_wakeup(struct device *dev, bool val);
/*函数device_init_wakeup,用来设置设备的唤醒相关功能,参数dev需要设置的设备,参数val,为1时,表示设备可以被唤醒,且使用唤醒功能;
为0时,表示设备不可以被唤醒。*/
static inline bool device_may_wakeup(struct device *dev);//该函数判断设备dev有没有设置能够使用唤醒
static inline int enable_irq_wake(unsigned int irq);//将一个中断设置为可将系统唤醒
static inline int disable_irq_wake(unsignedint irq);//将一个中断设置为可将系统唤醒

你可能感兴趣的:(驱动)