/sys/power/state

Posted mfmdaoyou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了/sys/power/state相关的知识,希望对你有一定的参考价值。

kernel/power/main.c中:

/**
 *	state - control system power state.
 *
 *	show() returns what states are supported, which is hard-coded to
 *	‘standby‘ (Power-On Suspend), ‘mem‘ (Suspend-to-RAM), and
 *	‘disk‘ (Suspend-to-Disk).
 *
 *	store() accepts one of those strings, translates it into the 
 *	proper enumerated value, and initiates a suspend transition.
 */
static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
			  char *buf)
{
	char *s = buf;
#ifdef CONFIG_SUSPEND
	int i;

	for (i = 0; i < PM_SUSPEND_MAX; i++) {
		if (pm_states[i] && valid_state(i))
			s += sprintf(s,"%s ", pm_states[i]);
	}
#endif
#ifdef CONFIG_HIBERNATION
	s += sprintf(s, "%s\n", "disk");
#else
	if (s != buf)
		/* convert the last space to a newline */
		*(s-1) = ‘\n‘;
#endif
	return (s - buf);
}

static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
			   const char *buf, size_t n)
{
#ifdef CONFIG_SUSPEND
#ifdef CONFIG_EARLYSUSPEND
	suspend_state_t state = PM_SUSPEND_ON;
#else
	suspend_state_t state = PM_SUSPEND_STANDBY;
#endif
	const char * const *s;
#endif
	char *p;
	int len;
	int error = -EINVAL;

	p = memchr(buf, ‘\n‘, n);
	len = p ?

p - buf : n; /* First, check if we are requested to hibernate */ if (len == 4 && !strncmp(buf, "disk", len)) { error = hibernate(); goto Exit; } #ifdef CONFIG_SUSPEND for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) { if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) break; } if (state < PM_SUSPEND_MAX && *s) { #ifdef CONFIG_EARLYSUSPEND if (state == PM_SUSPEND_ON || valid_state(state)) { error = 0; request_suspend_state(state); } #else error = enter_state(state); if (error) { suspend_stats.fail++; dpm_save_failed_errno(error); } else suspend_stats.success++; #endif } #endif Exit: return error ? error : n; } power_attr(state);

state_show()和state_store()即是用户层/sys/power/state的读写操作,power_attr属性的分析见博文:点击打开链接
state_show()显示了支持写入到/sys/power/state的字符串,它能够是:on, mem, standby, disk。

相应代码中的:

typedef int __bitwise suspend_state_t;

#define PM_SUSPEND_ON		((__force suspend_state_t) 0)
#define PM_SUSPEND_STANDBY	((__force suspend_state_t) 1)
#define PM_SUSPEND_MEM		((__force suspend_state_t) 3)
#define PM_SUSPEND_MAX		((__force suspend_state_t) 4)

state_store()即是写入操作:

它先推断是否是“disk“, 再比較是否是pm_states数组中的一个,pm_states定义在kernel/power/Suspend.c中:

const char *const pm_states[PM_SUSPEND_MAX] = {
#ifdef CONFIG_EARLYSUSPEND
	[PM_SUSPEND_ON]		= "on",
#endif
	[PM_SUSPEND_STANDBY]	= "standby",
	[PM_SUSPEND_MEM]	= "mem",
};

android中定义了CONFIG_EARLYSUSPEND,所以进入了kernel/power/Earlysuspend.c中的request_suspend_state函数:

void request_suspend_state(suspend_state_t new_state)
{
	unsigned long irqflags;
	int old_sleep;

	spin_lock_irqsave(&state_lock, irqflags);
	old_sleep = state & SUSPEND_REQUESTED;
	if (debug_mask & DEBUG_USER_STATE) {
		struct timespec ts;
		struct rtc_time tm;
		getnstimeofday(&ts);
		rtc_time_to_tm(ts.tv_sec, &tm);
		pr_info("request_suspend_state: %s (%d->%d) at %lld "
			"(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
			new_state != PM_SUSPEND_ON ? "sleep" : "wakeup",
			requested_suspend_state, new_state,
			ktime_to_ns(ktime_get()),
			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
			tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
	}
	if (!old_sleep && new_state != PM_SUSPEND_ON) {
		state |= SUSPEND_REQUESTED;
		queue_work(suspend_work_queue, &early_suspend_work);
	} else if (old_sleep && new_state == PM_SUSPEND_ON) {
		state &= ~SUSPEND_REQUESTED;
		wake_lock(&main_wake_lock);
		queue_work(suspend_work_queue, &late_resume_work);
	}
	requested_suspend_state = new_state;
	spin_unlock_irqrestore(&state_lock, irqflags);
}

这段代码的意思是当进入suspend前运行early_suspend_work,当从suspend状态恢复后运行late_resume_work。

这个文件里定义了它们:

static DECLARE_WORK(early_suspend_work, early_suspend);
static DECLARE_WORK(late_resume_work, late_resume);

early_suspend()将运行驱动程序中使用register_early_suspend()注冊了的suspend()函数。

late_resume()将运行驱动程序中使用register_early_suspend()注冊了的resume()函数。




以上是关于/sys/power/state的主要内容,如果未能解决你的问题,请参考以下文章

Linux 何时以及如何将 VGA 内存保存到 RAM?它在 pm-suspend 脚本中吗?或在 echo mem > /sys/power/state 之后的内核中

从sys/power/state分析并实现S3C2416的睡眠和唤醒

3系统睡眠模型

通过adb操作安卓亮屏设置背光亮度解锁打开app

Linux5.2/Documentation/power/basic-pm-debugging.txt 翻译 —— 调试休眠和挂起

ubuntu 电源管理