Linux内核Power_Management之suspend详解(一)

时间:2024-03-28 19:53:02

1.Linux内核的suspend状态

Linux内核支持多种类型睡眠状态,目前存在四种模式:suspend to idle(freeze)、power-on standby(standb)、suspend to ram(memory;STR)和suspend to disk(hibernate),分别对应ACPI状态的S0、S1、S3和S4状态。

State in Linux Label state ACPI  备注
#define  PM_SUSPEND_ON         ((__force suspend_state_t) 0)       正常
#define  PM_SUSPEND_FREEZE      ((__force suspend_state_t) 1) freeze suspend-to-idle S0 冻结进程+挂起设备+CPU空闲
#define  PM_SUSPEND_STANDBY    ((__force suspend_state_t) 2) standby power-on suspend S1 冻结进程+挂起设备+关闭nonbootCPU
#define  PM_SUSPEND_MEM     ((__force suspend_state_t) 3) mem suspend-to-ram S3 仅保留RAM自刷新
#define  PM_SUSPEND_MAX      ((__force suspend_state_t) 4) disk suspend-to-disk S4 关闭所有设备包括RAM,也被称为Hibernate
  • Suspend-To-Idle

        此状态包括frozen processes+suspended devices+idle processors,具有轻量化的特点;并且相对于相对于Idle状态能节省更多的功耗,因为此时的用户空间被冻结且I/O设备进入了低功耗状态。

        相对于Suspend-To-RAM它具有低延时的优势。

  • Power-On Suspend

        此状态简称standby状态,包括frozen processes+suspended devices+offline nonboot CPUs+suspend low-level system,对CPU的处理更近一步。所以相对于Suspend-To-Idle节省了更多的功耗,但是由于需要恢复CPU和一些底层功能也花费了更多的时间。

  • Suspend-to-RAM

        挂起到内存,简称待机。计算机将目前的运行状态等数据存放在内存,关闭硬 盘、外设等设备,进入等待状态。此时内存仍然需要电力维持其数据,但整机耗电很少。恢复时计算机从内存读出数据,回到挂起前的状态,恢复速度较快。对 DDR的耗电情况进行优化是S3性能的关键,大多数手持设备都是用S3待机。此状态下计算机会冻结所有的活动并将当前工作状态保存到RAM中,然后关闭屏幕进入低功耗模式,通常睡眠和唤醒需要几秒。此状态使所有的设备进入低功耗状态,仅保留RAM自刷新。所有的设备和系统状态都保存在RAM中,所有外设被挂起。

  • Suspend-to-disk

         此状态是最省功耗的模式,简称休眠。相对Suspend-to-RAM能节省更多功耗的原因是数据会被写入磁盘中,RAM也可以被关闭。但是这也导致了,更多的恢复延时,在resume的时候读回到RAM,然后在进行系统和设备状态恢复工作。把运行状态等数据存放在硬盘上某个文件或者某个特定的区域,关闭硬盘、外设等设备,进入关机状态。此时计算机完全关闭,不耗电。恢复时计算机从休眠文件/分区中读出数据,回到休眠前的状态,恢复速度较慢。电子书项目中,见过一款索尼的电子书,没有定义关机状态,只定义了S4,从而提高开机速度。一般在window系统中常见到。此状态下计算机将所有活动的状态保存到磁盘中,然后处于关机状态,此模式下是不耗电的,而相比之前的模式,休眠和唤醒的速度都比较慢。但是在一般的嵌入式设备上,此种状态不支持。

Linux内核Power_Management之suspend详解(一)

 

2. suspend相关代码分布

        kernel/power/main.c----提供用户空间接口(/sys/power/state)

        kernel/power/suspend.c----Suspend功能的主逻辑

        kernel/power/suspend_test.c----Suspend功能的测试逻辑

        kernel/power/console.c----Suspend过程中对控制台的处理逻辑

        kernel/power/process.c----Suspend过程中对进程的处理逻辑

        drivers/base/power/*----设备驱动相关电源管理处理逻辑

        include/linux/suspend.h----定义platform dependent PM有关的操作函数集

3. suspend流程概述

       本篇博客主要介绍Linux内核整个suspend的流程,及简单介绍函数的作用,函数内核源码的介绍放在下一篇中讲解。

       对/sys/power/state写入不同字符串,可以让系统进入不同睡眠状态。针对state sysfs节点的写入,最终会进入到state_store这个函数,将字符串转换成上表中不同状态。

        Linux内核suspend过程函数流程如下:

state_store()
    -->pm_suspend()
        -->enter_state()
            -->suspend_prepare()
                -->suspend_devices_and_enter()
                    -->suspend_enter()
                        -->suspend_finish()
  • state_store()

        解析用户传入的buffer(freeze、standby or mem),转换成state参数。state参数的类型为suspend_state_t,在include\linux\suspend.h中定义,为电源管理状态在内核中的表示。根据state的值,如果不是(PM_SUSPEND_MAX,对应hibernate功能),则调用pm_suspend接口,进行后续的处理。 

  • pm_suspend()

        pm_suspend()函数在kernel/power/suspend.c定义,判断处理所有的freeze、standby和mem三种类型的suspend。

  • enter_state()

        enter_state()函数是suspend的入口点,是进入系统睡眠所需的公共准备工作。

  • suspend_prepare()

        suspend_prepare()函数是进入suspend前的准备,主要包含选择控制台和进程冻结,如果失败,则终止suspend。

  • suspend_device_and_enter()

        suspend_device_and_enter()函数是对suspend和resume的所有实际操作,这是一个对称的流程,每一个阶段的suspend,都有相应的resume。

  • suspend_enter()

        suspend_enter()函数当所有的设备都挂起之后才会被调用,这个函数里才是freeze、standby和mem的区别所在。

  • suspend_finish()

        suspend_finish()解冻重启进程,发送PM_POST_SUSPEND通知释放之前分配的控制台。