/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()函数。

时间: 2024-10-10 06:33:03

/sys/power/state的相关文章

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

环境: PC: debian-7.6.0 ARM CPU: S3C2416 Linux-Kernel: 3.6.0(FriendlyARM) U-boot: 1.3.4 一.问题来源 根据需要,在S3C2416上添加中断睡眠和唤醒功能,于是我就查查Linux支持S3C2416的睡眠模式: cat /sys/power/state 执行完,万万没想到:竟然是空的,该命令没有任何输出!也就是说,我的内核目前不支持任何方式的睡眠. 不可能啊!之前我用S3C2440的CPU(内核版本Linux_2_6_

/sys/power/pm_async 文件解读

参考: 1.system suspend/resume过程中的异步操作pm_async:https://blog.csdn.net/dachai/article/details/103805313 这个博文中描述的device_suspend()中在4.14内核中还没有dpm_async_fn,这个应该是5.x的内核中才有的功能.2.使用sleepgraph工具分析并优化suspend/resume流程:https://blog.csdn.net/dachai/article/details/1

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

调试休眠和挂起 (C) 2007 Rafael J. Wysocki <[email protected]>, GPL 1.测试休眠(即挂起到磁盘或STD) 要检查休眠是否有效,您可以尝试在 "reboot" 模式下休眠: # echo reboot > /sys/power/disk # echo disk > /sys/power/state 并且系统应创建休眠镜像,重新启动,恢复并返回到已开始转换的命令提示符. 如果发生这种情况,休眠最有可能正常工作. 尽

S3C2416睡眠的底层实现

环境: ARM CPU: S3C2416 Linux-Kernel: 3.6.0 针对S3C2416睡眠和唤醒的实现方法,参见上一篇: 从sys/power/state分析并实现S3C2416的睡眠和唤醒 本文分析S3C2416睡眠的底层实现,分两个部分: 1.CPU相关的实现过程 2.内核怎么把睡眠唤醒的功能加入 一.CPU相关的实现过程 S3C2416睡眠的寄存器设置在pm-s3c2416.c中(同色为调用关系) arch/arm/mach-s3c24xx/pm-s3c2416.c stat

linux驱动程序之电源管理 之linux休眠与唤醒(2)

在Linux中,休眠主要分三个主要的步骤:(1)冻结用户态进程和内核态任务:(2)调用注册的设备的suspend的回调函数:(3)按照注册顺序休眠核心设备和使CPU进入休眠态.       冻结进程是内核把进程列表中所有的进程的状态都设置为停止,并且保存下所有进程的上下文.当这些进程被解冻的时候,他们是不知道自己被冻结过的,只是简单的继续执行.如何让Linux进入休眠呢?用户可以通过读写sys文件/sys /power/state 是实现控制系统进入休眠.比如: # echo standby >

电脑睡眠状态(ACPI规范定义了七个状态,使用powercfg -a进行查看)

ACPI规范定义了一台兼容ACPI的计算机系统可以有以下七个状态(所谓的全局状态): G0('S0)正常工作状态:计算机的正常工作状态-操作系统和应用程序都在运行.CPU(s)执行指令.在这个状态下(即没有进入G1睡眠),CPU和像硬盘.DVD驱动器等等这些的设备可以一再的进入和从低能源状态回来,叫做C0-Cn和D0-D3.(例如膝上型计算机,当使用电池运行的时候通常关掉所有当前未使用的设备:一些桌面型计算机也这么做来减少噪声.) G1 睡眠 细分为从S1到S4这四种状态.系统从这几种状态被唤醒

Suspend to RAM和Suspend to Idle分析,以及在HiKey上性能对比

Linux内核suspend状态 Linux内核支持多种类型的睡眠状态,通过设置不同的模块进入低功耗模式来达到省电功能.目前存在四种模式:suspend to idle.power-on standby(Standby).suspend to ram(STR)和sudpend to disk(Hibernate),分别对应ACPI状态的S0.S1.S3和S4. Suspend to idle完全是软件相关的并且尽量将CPU维持在深度idle状态. Power-on standby设置设备进入低功

android init进程分析

android的init进程用来启动zygote进程,用来启动android世界.init进程的源码在顶层目录的/system/core/init使用 find -name Android.mk -exec grep -l "init" {} \;来查找源码,接下来的android服务程序也是使用这个指令来查找源码. /system/core/init/init.c 整个init进程的入口函数669 int main(int argc, char **argv) init_parse_

Android 启动过程的底层实现

转载请标明出处: http://blog.csdn.net/yujun411522/article/details/46367787 本文出自:[yujun411522的博客] 3.1 android正常模式启动流程 主要流程例如以下: 1.系统加电.运行bootloader,bootloader会将内核载入到内存中. 2.内核载入到内存之后首先进入内核引导阶段,最后调用start_kernel进入内核启动.start_kernel终于会启动init程序 3.init程序负责解析init.rc文