android 休眠唤醒机制分析(一) — wake_lock

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

一、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对外提供的操作接口:

1、内核空间接口

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()用于初始化一个新锁,type参数指定了锁的类型;wake_lock_destroy()则注销一个锁;wake_lock()和wake_lock_timeout()用于将初始化完成的锁激活,使之成为有效的永久锁或者超时锁;wake_unlock()用于解锁使之成为无效锁。另外还有两个接口:

int wake_lock_active(struct wake_lock *lock);
long has_wake_lock(int type);

其中wake_lock_active()用于判断锁当前是否有效,如果有效则返回非0值;has_wake_lock()用于判断系统中是否还存在有效的type型锁,如果存在超时锁则返回最长的一个锁的超时时间,如果存在永久锁则返回-1,如果系统中不存在有效锁则返回0。

2、用户空间接口

wake_lock向用户空间提供了两个文件节点用于申请锁和解锁:

// wack_lock文件的读函数,显示用户空间定义的有效锁
ssize_t wake_lock_show(
	struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
	char *s = buf;
	char *end = buf + PAGE_SIZE;
	struct rb_node *n;
	struct user_wake_lock *l;

	mutex_lock(&tree_lock);

	for (n = rb_first(&user_wake_locks); n != NULL; n = rb_next(n)) {
		l = rb_entry(n, struct user_wake_lock, node);
		if (wake_lock_active(&l->wake_lock))
			s += scnprintf(s, end - s, "%s ", l->name);
	}
	s += scnprintf(s, end - s, "\n");

	mutex_unlock(&tree_lock);
	return (s - buf);
}

// wack_lock文件的写函数,初始化并激活用户空间定义的锁
ssize_t wake_lock_store(
	struct kobject *kobj, struct kobj_attribute *attr,
	const char *buf, size_t n)
{
	long timeout;
	struct user_wake_lock *l;

	mutex_lock(&tree_lock);
	l = lookup_wake_lock_name(buf, 1, &timeout);
	if (IS_ERR(l)) {
		n = PTR_ERR(l);
		goto bad_name;
	}

	if (debug_mask & DEBUG_ACCESS)
		pr_info("wake_lock_store: %s, timeout %ld\n", l->name, timeout);

	if (timeout)
		wake_lock_timeout(&l->wake_lock, timeout);
	else
		wake_lock(&l->wake_lock);
bad_name:
	mutex_unlock(&tree_lock);
	return n;
}

// wack_unlock文件的读函数,显示用户空间的无效锁
ssize_t wake_unlock_show(
	struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
	char *s = buf;
	char *end = buf + PAGE_SIZE;
	struct rb_node *n;
	struct user_wake_lock *l;

	mutex_lock(&tree_lock);

	for (n = rb_first(&user_wake_locks); n != NULL; n = rb_next(n)) {
		l = rb_entry(n, struct user_wake_lock, node);
		if (!wake_lock_active(&l->wake_lock))
			s += scnprintf(s, end - s, "%s ", l->name);
	}
	s += scnprintf(s, end - s, "\n");

	mutex_unlock(&tree_lock);
	return (s - buf);
}

// wack_unlock文件的写函数,用于用户空间解锁
ssize_t wake_unlock_store(
	struct kobject *kobj, struct kobj_attribute *attr,
	const char *buf, size_t n)
{
	struct user_wake_lock *l;

	mutex_lock(&tree_lock);
	l = lookup_wake_lock_name(buf, 0, NULL);
	if (IS_ERR(l)) {
		n = PTR_ERR(l);
		goto not_found;
	}

	if (debug_mask & DEBUG_ACCESS)
		pr_info("wake_unlock_store: %s\n", l->name);

	wake_unlock(&l->wake_lock);
not_found:
	mutex_unlock(&tree_lock);
	return n;
}

power_attr(wake_lock);
power_attr(wake_unlock);
这两个文件节点分别为"/sys/power/wake_lock"和"/sys/power/wake_unlock",应用程序可以根据HAL层的接口读写这两个节点。
二、wake_lock 实现
在linux/kernel/power/wakelock.c中我们可以看到wake_lock的实现代码,首先看看其定义的一些初始化信息:

#define WAKE_LOCK_TYPE_MASK              (0x0f)     // 锁类型标志掩码
#define WAKE_LOCK_INITIALIZED            (1U << 8)  // 锁已经初始化标志
#define WAKE_LOCK_ACTIVE                 (1U << 9)  // 锁有效标志
#define WAKE_
  • 14
    点赞
  • 124
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android 休眠唤醒机制是指在设备进入休眠(睡眠)状态后,如何触发设备的唤醒操作。在 Android 系统中,休眠是指将设备的 CPU、屏幕和其他硬件组件进入低功耗状态,以节省电量。休眠状态下,应用程序的运行和响应暂时被挂起,但系统仍然会保持一些必要的功能在后台运行。 当设备进入休眠状态后,有两种方式可以唤醒设备。第一种方式是通过外部事件唤醒,例如用户按下了电源键或其他物理按键、插入了充电器、接收到电话等。此时,系统会接收到相应的事件信号,并触发设备的唤醒操作。第二种方式是通过定时器唤醒,也就是设备设置了一个特定的时间,在到达该时间时自动唤醒设备。 在 Android 系统中,可以使用的休眠唤醒机制有以下几种: 1. AlarmManager:通过定时器来唤醒设备。可以使用 setExact() 方法设置精确的唤醒时间,或者使用 setWindow() 方法设置一个时间范围,在该范围内唤醒设备。 2. BroadcastReceiver:可以注册一个广播接收器,在接收到指定的广播消息时,唤醒设备。常用的广播消息有BOOT_COMPLETED(设备启动完成时)、ACTION_SCREEN_ON(屏幕亮起时)、ACTION_USER_PRESENT(屏幕解锁时)等。 3. WakeLock:可以通过申请 WakeLock 来保持设备唤醒状态,直到释放 WakeLock 或达到指定的时间。常用的 WakeLock 参数有 PARTIAL_WAKE_LOCK(保持 CPU 运转)、SCREEN_DIM_WAKE_LOCK(保持屏幕亮起时)等。 总的来说,Android 休眠唤醒机制提供了多种方式来唤醒设备,开发者可以根据自己的需求选择适合的方式。但需要注意的是,过度使用休眠唤醒机制会增加设备耗电量,降低系统性能,因此需要合理使用并进行优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值