linux的睡眠框架及实现

睡眠 4 种模式:

  • S2I (Suspend-to-Idle): 挂起系统,IO进入低功耗模式。需配置CONFIG_SUSPEND。

  • Standby:执行S2I后,把AP (nonboot CPU) 离线。除了CONFIG_SUSPEND的支持外,还需要向suspend子系统注册,如果是基于ACPI的系统,需要映射到S1状态。

  • S2RAM(Suspend-to-RAM):又称为STR,系统状态保存到内存,所有的外围设备,总线都进入低功耗或者断电的状态,内核在最后一步会把控制权给到BIOS,并映射到S3状态(ACPI系统)。除了CONFIG_SUSPEND的支持外,还需要向suspend子系统注册。

  • Hibernation(Suspend-to-Disk or STD) : 创建当前系统的内存镜像(内核和应用进程),保存到硬盘,然后,系统断电或者进入低功耗模式。唤醒时,bios启动一个新的内核(恢复内核)加载内存镜像,新内核自我更新,恢复先前的内核和进程状态。需要CONFIG_HIBERNATION的支持。

sys 接口

/sys/power/state (kernel/power/main.c)

  • state_show: 对应的read函数。

  • state_store:对应的write函数。

stat_show( )显示系统可用到睡眠模式,pm_states_init( ) 会初始化状态,其中S2I和 S2RAM是默认支持的,Standby 和 Hibernation 则需要进行检测硬件平台是否系统支持,不支持的话,就不会显示出来,显示值依次是:freeze,standby,mem,disk.

sys接口是功能的入口,从 stat_store( ) 里可以看到待机和休眠的入口函数分别是:

  • pm_suspend(state)

  • hibernate()

待机(SUSPEND)

入口:int pm_suspend(suspend_state_t state),有效参数是:

  • #define PM_SUSPEND_TO_IDLE ((__force suspend_state_t) 1)

  • #define PM_SUSPEND_STANDBY ((__force suspend_state_t) 2)

  • #define PM_SUSPEND_MEM ((__force suspend_state_t) 3)

待机可以分为3个阶段:

1: 准备阶段

主要是冻结应用程序和内核线程,外设进入睡眠状态。这个是公共部分,所有的suspend状态都要执行。

下图时一个基本的流程框架。

(suspend的流程框架图)

冻结程序

修改用户进程状态为 PF_FROZEN,使任务并进入__refrigerator( )里的一个循环,直到被唤醒——称之为 freeze。内核线程也是类似的情况,它进入另外的循环。freeze不是强制的,创建时可以配置为不可冻结。

冻结程序和内核线程的主要原因是:防止休眠时文件系统因为读写而损坏;防止驱动读写一个已经挂起的设备;等等(详见freezing-of-tasks.rst)。打开refrigerator( )里日志可以看到如下消息:

    Freezing user space processes ... 
    systemd entered refrigerator
    gdbus entered refrigerator
    emacs entered refrigerator
    bash entered refrigerator

当前系统所有的应用程序都被冻结了,系统唤醒后,各任务退出循环,继续运行。

设备待机

主要是在DPM(device power manager,base/power/main.c)模块的 dpm_suspend( )中实现,轮询 dpm设备list,依次调用 device_suspend(dev) 来 callback每个设备注册的suspend( ). 以pci设备为例:

    struct bus_type pci_bus_typs = { .pm        = PCI_PM_OPS_PTR,}
    struct dev_pm_ops pci_dev_pm_ops = {.suspend = pci_pm_suspend, ...}

因此,每个pci设备都是先callback pci_pm_suspend( ),在这个函数里再callback各个设备的 pm->suspend(dev) 。

dpm list是通过 device_add( ) --> device_pm_add( ) 来生成的,也就是添加设备时,进行检测,支持PM管理的设备会被放入 dmp list,当执行suspend时,轮询该列表依次callback各个设备注册的 suspend函数。

2: 进入待机

这个阶段主要时执行底层函数,进入待机状态,具体实现同CPU架构相关。

入口是 suspend_enter( ),先检测pm状态,如果是S2I,则走s2idle_loop( ),不需要待机。否则走 syscore_suspend( ),先轮询syscore_ops_list,执行每个对象的suspend( ), 最后,调用平台相关的suspend_ops->enter(state),执行cpu模块的底层函数,写数据到bios后,系统由bios接管,进入待机状态。

syscore_ops_list 通过register_syscore_ops( )(drivers/base/syscore.c)来注册,一般在同cpu架构相关的代码里面。suspend_ops是通过suspend_set_ops( )来注册的,以龙芯mips为例:

suspend_set_ops(&loongson_pm_ops);
suspend_ops->enter -->loongson_pm_enter
-->mach_suspend: (arch/mips/loongson64/loongson-3/pm.c)-->保存一些寄存器
-->loongson_suspend_enter: (arch/mips/loongson64/loongson-3/sleep.S)
   写数据到bios后待机,系统在当前位置挂机,bios开始接管系统。

3: 恢复

待机后,系统就挂在当前的执行位置,当用户唤醒(按电源键或者键盘)系统时,bios先恢复CPU,然后CPU从当前位置开始唤醒系统,唤醒刚好是一个相反的过程,先从架构相关的底层开始,逐级唤醒系统,主要的代码流程是在 suspend_enter( )的后半段,也是从suspend_ops->enter( ) 开始,这个函数的退出,表示系统已开始唤醒,接着syscore_resume( ) -->... --> ahci_pci_device_resume ( ) ....;依次调用各模块的 resume( ) callback。

休眠(Hibernation)

入口是 hibernate( ) kernel/power/hibernate.c,主要的工作流程都在这个函数里面。

休眠的3种模式

cat /sys/power/disk 可以看到休眠支持的3种模式:

  • 'platform': 检测是否有平台支持(ACPI等),进入平台的待机模式。

  • 'shutdown':关机。

  • 'reboot': 重启,功能测试用。

工作流程

  • freeze_processes

  • freeze_kernel_threads()

  • dpm_suspend(PMSG_FREEZE)

  • create_image(platform_mode)

  • dpm_resume(msg)

  • swsusp_write(flags)

  • power_down( )

上面的函数流已经可以自解释了,先是冻结用户进程和内核线程,接着设备也进入待机,已防后面创建镜像时出现bug,镜像创建后,恢复设备,为关机做准备。最后的步骤是镜像写入交换分区,然后关机。

恢复的入口函数是:software_resume( ),加载内存镜像后,内核自我更新状态,恢复先前的状态。

ACPI

ACPI在睡眠框架里不是必选项,不是所有的架构都支持ACPI。它的入口是acpi_sleep_init( ) (drivers/acpi/sleep.c),主要是3个初始化函数:

  • acpi_sleep_syscore_init();

  • acpi_sleep_suspend_setup();

  • acpi_sleep_hibernate_setup();

分别注册对应级别的callback,当系统睡眠时,它会callback ACPI中相关的函数,与bios进行通讯,完成对应的睡眠功能。

参考资料

Documentation/admin-guide/pm/sleep-status.rst

Documentation/power/freezing-of-tasks.rst

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值