Linux电源管理5

Linux电源管理5(基于Linux6.6)---Generic PM Suspend介绍

 


一、概述

Linux内核提供了三种Suspend: Freeze、Standby和STR(Suspend to RAM),在用户空间向”/sys/power/state”文件分别写入”freeze”、”standby”和”mem”,即可触发它们。

在 Linux 内核中,Suspend 是一种电源管理机制,允许操作系统将系统的某些部分或整个系统置于低功耗状态,以延长电池寿命或减少能耗。Linux 提供了几种不同的挂起模式,常见的有 FreezeStandbySTR (Suspend to RAM),它们分别有不同的行为和适用场景。

以下是这三种挂起模式的概述:

1.1、Freeze (冻结模式)

Freeze 是一种较轻的挂起模式,系统中的设备和进程会被冻结,但 CPU 和内存仍然处于活动状态。

  • 工作原理:在 Freeze 模式下,操作系统会暂停所有进程的执行,尤其是用户空间的进程。内核会冻结所有与进程相关的活动,保持系统的基本状态不变。硬件设备可能会进入低功耗模式,但 CPU 会保持活动状态,内存内容保持不变。

  • 使用场景:此模式通常用于需要快速恢复的场景,因为设备和内存状态都没有被完全关闭。设备的驱动程序可能会停止处理数据或任务,但内存中的数据保持完整,允许较短时间内恢复操作。

  • 优点:恢复速度较快,因为系统状态没有被完全重置。

  • 缺点:与其他更深层次的挂起模式相比,能效较低,因为 CPU 和内存仍在消耗电力。

1.2、Standby (待机模式)

Standby 模式是一个中间级别的挂起模式,系统的部分硬件可能会关闭,但 CPU 和内存依然保持活动状态。

  • 工作原理:在 Standby 模式下,操作系统将尽量减少硬件的活动以节省电力。通常,待机模式下系统会关闭一些硬件设备,如硬盘、显示器等,但 CPU 和内存继续工作。类似于冻结模式,但是 Standby 模式下可能允许更多的硬件进入低功耗状态。

  • 使用场景:适用于不需要完全关闭设备、但仍需要降低功耗的场景。Standby 模式常用于移动设备中,以便在短时间内快速恢复工作。

  • 优点:比 Freeze 模式节省更多电力,恢复速度通常较快。

  • 缺点:虽然比 Freeze 模式更节能,但恢复速度略慢,设备的一部分仍然处于活动状态。

1.3、STR (Suspend to RAM) - 睡眠模式

STR (Suspend to RAM),也称为 Suspend to RAM睡眠模式,是一种深度挂起模式,系统会将大部分硬件和设备的电源关闭,同时将内存的内容保留在 RAM 中。

  • 工作原理:在 STR 模式下,CPU 会完全停止工作,硬件大部分会进入休眠状态,只有内存仍然保持活动(即保持电力供应)。内存中保存着系统的当前状态,包括正在运行的进程和数据。此时,内存的内容被保留在 RAM 中,电力供应给内存,以确保系统可以从挂起状态中快速恢复。

  • 使用场景:STR 模式适用于需要较长时间节省电力的情况,尤其是在笔记本电脑和移动设备上,当设备长时间不使用时,进入该模式以延长电池寿命。

  • 优点

    • 最大限度减少电力消耗,因为大部分硬件被关闭。
    • 恢复速度相对较快,因为系统的状态保存在内存中,恢复时无需重新启动。
  • 缺点

    • 内存需要持续供电,否则数据会丢失。此模式对电池的依赖较大。
    • 在某些硬件平台上,恢复过程可能不如预期顺利,存在硬件兼容性问题。

各模式的比较

模式 电源消耗 恢复速度 使用场景 特点
Freeze 较低 非常快 快速挂起并恢复,保持进程状态 冻结进程,保持内存,但不关闭硬件
Standby 中等 短时间内降低功耗 部分硬件关闭,但 CPU 和内存继续活动
STR 非常低 长时间节省电力,适合闲置时 CPU 停止,内存内容保持,硬件大部分关闭

 

二、 suspend&resume过程概述

下面图片对Linux suspend&resume过程做了一个概述:

三、代码分析

3.1、suspend入口

在用户空间执行如下操作:

会通过sysfs触发suspend的执行,相应的处理代码如下:

static ssize_t state_store(struct device *dev, struct device_attribute *attr,
			   const char *buf, size_t count)
{
	const int online_type = mhp_online_type_from_str(buf);
	struct memory_block *mem = to_memory_block(dev);
	int ret;

	if (online_type < 0)
		return -EINVAL;

	ret = lock_device_hotplug_sysfs();
	if (ret)
		return ret;

	switch (online_type) {
	case MMOP_ONLINE_KERNEL:
	case MMOP_ONLINE_MOVABLE:
	case MMOP_ONLINE:
		/* mem->online_type is protected by device_hotplug_lock */
		mem->online_type = online_type;
		ret = device_online(&mem->dev);
		break;
	case MMOP_OFFLINE:
		ret = device_offline(&mem->dev);
		break;
	default:
		ret = -EINVAL; /* should never happen */
	}

	unlock_device_hotplug();

	if (ret < 0)
		return ret;
	if (ret)
		return -EINVAL;

	return count;
}

power_attr定义了一个名称为state的attribute文件,该文件的store接口为state_store,该接口在lock住autosleep功能后,解析用户传入的buffer(freeze、standby or mem),转换成state参数。

state参数的类型为suspend_state_t,在include\linux\suspend.h中定义,为电源管理状态在内核中的表示。具体如下:

typedef int __bitwise suspend_state_t;
 
#define PM_SUSPEND_ON           ((__force suspend_state_t) 0)
#define PM_SUSPEND_FREEZE       ((__force suspend_state_t) 1)
#define PM_SUSPEND_STANDBY      ((__force suspend_state_t) 2)
#define PM_SUSPEND_MEM          ((__force suspend_state_t) 3)
#define PM_SUSPEND_MIN          PM_SUSPEND_FREEZE
#define PM_SUSPEND_MAX          ((__force suspend_state_t) 4)

根据state的值,如果不是(PM_SUSPEND_MAX,对应hibernate功能),则调用pm_suspend接口,进行后续的处理。 

pm_suspend在kernel/power/suspend.c定义,处理所有的suspend过程。  

3.2、pm_suspend & enter_state

pm_suspend的实现非常简单,简单的做一下参数合法性判断,直接调用enter_state接口,如下:

/**
 * pm_suspend - Externally visible function for suspending the system.
 * @state: System sleep state to enter.
 *
 * Check if the value of @state represents one of the supported states,
 * execute enter_state() and update system suspend statistics.
 */
int pm_suspend(suspend_state_t state)
{
	int error;

	if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX)
		return -EINVAL;

	pr_info("suspend entry (%s)\n", mem_sleep_labels[state]);
	error = enter_state(state);
	if (error) {
		suspend_stats.fail++;
		dpm_save_failed_errno(error);
	} else {
		suspend_stats.success++;
	}
	pr_info("suspend exit\n");
	return error;
}
EXPORT_SYMBOL(pm_suspend);

enter_state代码为:

/**
 * enter_state - Do common work needed to enter system sleep state.
 * @state: System sleep state to enter.
 *
 * Make sure that no one else is trying to put the system into a sleep state.
 * Fail if that's not the case.  Otherwise, prepare for system suspend, make the
 * system enter the given sleep state and clean up after wakeup.
 */
static int enter_state(suspend_state_t state)
{
	int error;

	trace_suspend_resume(TPS("suspend_enter"), state, true);
	if (state == PM_SUSPEND_TO_IDLE) {
#ifdef CONFIG_PM_DEBUG
		if (pm_test_level != TEST_NONE && pm_test_level <= TEST_CPUS) {
			pr_warn("Unsupported test mode for suspend to idle, please choose none/freezer/devices/platform.\n");
			return -EAGAIN;
		}
#endif
	} else if (!valid_state(state)) {
		return -EINVAL;
	}
	if (!mutex_trylock(&system_transition_mutex))
		return -EBUSY;

	if (state == PM_SUSPEND_TO_IDLE)
		s2idle_begin();

	if (sync_on_suspend_enabled) {
		trace_suspend_resume(TPS("sync_filesystems"), 0, true);
		ksys_sync_helper();
		trace_suspend_resume(TPS("sync_filesystems"), 0, false);
	}

	pm_pr_dbg("Preparing system for sleep (%s)\n", mem_sleep_lab
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值