linux 中 ACPI 电源管理 G 状态、S 状态、D 状态、C 状态、P 状态
ACPI 高级电源管理
ACPI 中定义了 G、D、S、C、P 这 5 个大的电力状态。
G 状态 Global system state
G 状态表示的是用户看到的整个系统的电力状态。
-
G0 运行模式。向硬件提供电源,软件可以运行的状态。
-
G1 停止模式。所谓的待机或休眠状态。
-
G2 软件为关闭状态,应将消耗若干电力状态。
-
G3 系统完全关闭,电源关闭的状态。
S 状态
-
S0 运行模式,与 G0 相同。
-
S1 到恢复为止的延迟时间较少的停止模式。 CPU 的上下文不会丢失。
-
S2 丢失 CPU 和系统缓存上下文。这些上下文需要在系统唤醒时进行恢复。在 Linux 中与 S3 相同。
-
S3 丢失除软件以外的系统上下文。这些上下文需要在操作系统唤醒时进行恢复。
-
S4 最省电。到恢复为止花费时间最多的停止模式。停止向所有设备提供电源
-
S5 除了不保存上下文以外,其它与 S4 相同。 S5 在恢复时进行的处理与普通的操作系统相同。与 G2 含义相同。
D 状态
Device Power State 定义的是各个设备的电力状态,设备的状态有如下内容:
- 耗电量
- 保存设备内寄存器上下文的状态
- 直到设备驱动程序可使用为止必须进行的操作量
- 直到设备可使用为止需要的时间
不同的子状态描述如下:
-
D0 设备可以完全运行的状态。所有上下文全部有效,最耗电。
-
D1 对于每个设备的意义不同。一般来说,耗电量比 D0 少,丢失的上下文比 D2 更少
-
D2 对于每个设备类型的意义也不同。一般来说,耗电量比 D1 更少,丢失的上下文比 D1 更多。
-
D3hot 对于每个设备类型的意义不同。D3hot 状态的设备主电源开启,可以从软件访问设备。但上下文是否能保留取决于实际安装的设备。D3 设备电源完全断开的状态。设备的上下文全部丢失,到恢复为止花的时间最长。在 PCI 用语中称为 D3cold。PCI 中常常将 D3hot 与 D3cold 统称为 D3
C 状态
Processor Power State 是 G0 中 CPU 空闲时进行的省电模式。
-
C0 运行中的状态。通常的运行模式。
-
C1 CPU 停止状态。使用 hlt 命令停止 CPU 的时钟,到恢复为止几乎没有延迟时间,软件不需进行特殊处理。
-
C2 总线的时钟也停止。恢复所花费的最长延时时间传递给 ACPI 的固件,操作系统基于这个延时时间判断使用 C1 还是 C2。
-
C3 将花费时间最长的延迟传递给 ACPI 固件,操作系统使用这个延迟时间判断使用 C2 还是 C3。操作系统需要考虑缓存的同步。
使用 C 状态时要注意,C 状态的程度越深,恢复到 C0 状态所需的时间越长。
P 状态
全称为 Device and Processor Performance State
P 状态是以控制电量消耗来降低设备或 CPU 的性能,对 D0 状态的设备、C0 状态的 CPU 进行了更细致的划分。
-
P0 通常的模式。以最高性能、最大耗电量运行。
-
P1 运行在低于最高性能、最大耗电量的模式 Pn n 的值越大,性能和耗电量越低。
ACPI 的结构
- ACPI 系统描述表
- ACPI 寄存器
- ACPI BIOS
ACPI 描述表在 ACPI 的接口中是核心的组件,提供 ACPI 寄存器等信息。ACPI BIOS 可以 提供 ACPI 系统描述表以及启动、停止、唤醒等功能。
两个编程模型
ACPI 的硬件模型有下面两种:
固定硬件编程模型
使用 ACPI 中定义的寄存器来访问 ACPI 的功能。
通用硬件编程模型
各厂商可以使用 ACPI Machine Language 将硬件固有的处理安装到 BIOS 中。操作系统可 以通过分析 BIOS 提供的 AML 代码,来理解就餐器的地址和访问方法等。
AML 是二进制码,通过编译 ACPI Source language 来生成。操作系统分析 AML 将 AML中 所写的内容按照解释器来执行。
ACPI 系统描述表
可以通过 pmtools 与 iasl 相关的命令来查看。执行如下命令安装这两个程序:
sudo apt-get install pmtools sudo apt-get install iasl
运行示例如下:
root@debian:~# acpidump -b -o dsdt.dat
root@debian:~# ls apic.dat boot.dat dsdt.dat facp.dat facs.dat hpet.dat mcfg.dat srat.dat waet.dat
root@debian:~# ls apic.dat boot.dat dsdt.dat facp.dat facs.dat hpet.dat mcfg.dat srat.dat waet.dat root@debian:~#
root@debian:~# iasl -d dsdt.dat
Intel ACPI Component Architecture
ASL+ Optimizing Compiler/Disassembler version 20181213
Copyright (c) 2000 - 2018 Intel Corporation
Input file dsdt.dat, Length 0x1368A (79498) bytes
ACPI: DSDT 0x0000000000000000 01368A (v01 PTLTD Custom 06040000 MSFT 03000001)
Pass 1 parse of [DSDT]
Pass 2 parse of [DSDT]
Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)
Parsing completed
Disassembly completed
ASL Output: dsdt.dsl - 729339 bytes
root@debian:~# head -n 30 dsdt.dsl
/*
* Intel ACPI Component Architecture
* AML/ASL+ Disassembler version 20181213 (64-bit version)
* Copyright (c) 2000 - 2018 Intel Corporation
*
* Disassembling to symbolic ASL+ operators
*
* Disassembly of dsdt.dat, Mon Aug 10 12:43:44 2020
*
* Original Table Header:
* Signature "DSDT"
* Length 0x0001368A (79498)
* Revision 0x01 **** 32-bit table (V1), no 64-bit math support
* Checksum 0x63
* OEM ID "PTLTD "
* OEM Table ID "Custom "
* OEM Revision 0x06040000 (100925440)
* Compiler ID "MSFT"
* Compiler Version 0x03000001 (50331649)
*/
DefinitionBlock ("", "DSDT", 1, "PTLTD ", "Custom ", 0x06040000)
{
External (_SB_.L1M0.L0MX, IntObj)
External (_SB_.L1M1.L0MX, IntObj)
External (_SB_.L1M2.L0MX, IntObj)
External (_SB_.L1M3.L0MX, IntObj)
External (_SB_.L1M4.L0MX, IntObj)
External (_SB_.L1M5.L0MX, IntObj)
External (_SB_.L1M6.L0MX, IntObj)
External (_SB_.L1M7.L0MX, IntObj)
使用 ACPI 的 S 状态
查看支持的 S 状态:
root@debian:~# cat /sys/power/state
freeze standby mem disk
standby S1 mem S3 disk S4
切换状态:
echo "状态字符串" > /sys/power/state
执行示例:
root@debian:~# echo "mem" > /sys/power/state
按下电源键就可以恢复。
S3 状态的结构
使用 S3 状态时,不同系统的反应不同,大致操作如下:
- 停止进程
- 停止设备运行
- 将唤醒时的开始地址作为 Wakeup vector 登录到 BIOS
- 停止 BSP (Boot Strap Processor) 以外的 CPU 运行
- 停止系统设备运行
- 保存内核和 CPU 的状态
- 将获取到的 ACPI 的 _S3 对象得到的值写入 FADT 的 PM1 寄存器,进入待机模式。
- 系统恢复时,从登录到 wakeup vector 的地址启动,按下列方式恢复到待机前的状态
- 启用 ACPI
- 恢复系统设备
- 启用 CPU
- 清除 wakeup vector
- 恢复停止的设备
- 恢复进程
S4 状态的使用方法
linux 中 S4 称为 swap 待机,有内核的 S4 处理通过将内存上的所有数据保存在交换区磁盘来停止电源,恢复时由 bootloader 启动内核,在内核初始化时,把之前保存到交换区磁盘的数据读入内存来快速回复到原来的状态。
使用方法如下:
echo "platform" > /sys/power/disk
echo "disk" > /sys/power/state
休眠要使用交换区磁盘,一般需要准备内存的 1.5 ~ 2 倍的磁盘容量。这应该就是 swap 要设置为 2 倍内存大小的原因。
在我的系统中,默认保存在交换区磁盘的内存大小如下:
longyu@debian:~$ cat /sys/power/image_size 814505984
执行如下命令来取消限制。
echo "0" > /sys/power/image_size
执行一次休眠后按电源键重新启动系统后查看 dmesg 信息,有如下相关信息:
[ 759.283304] PM: hibernation entry
[ 759.285989] PM: Syncing filesystems ...
[ 759.289551] PM: done.
[ 759.289552] Freezing user space processes ... (elapsed 0.001 seconds) done.
[ 759.291357] OOM killer disabled.
[ 759.291465] PM: Marking nosave pages: [mem 0x00000000-0x00000fff]
[ 759.291466] PM: Marking nosave pages: [mem 0x0009e000-0x000fffff]
[ 759.291467] PM: Marking nosave pages: [mem 0x7fee0000-0x7fefffff]
[ 759.291468] PM: Basic memory bitmaps created
[ 759.291505] PM: Preallocating image memory... done (allocated 95921 pages)
[ 759.339329] PM: Allocated 383684 kbytes in 0.04 seconds (9592.10 MB/s)
[ 759.339330] Freezing remaining freezable tasks ... (elapsed 0.002 seconds) done.
[ 759.342363] Suspending console(s) (use no_console_suspend to debug)
[ 759.343092] serial 00:05: disabled
[ 759.376353] mptbase: ioc0: pci-suspend: pdev=0x0000000010a726cd, slot=0000:00:10.0, Entering operating state [D0]
[ 759.457082] ACPI: Preparing to enter system sleep state S4
[ 759.457366] PM: Saving platform NVS memory
[ 759.457368] Disabling non-boot CPUs ...
[ 759.494741] smpboot: CPU 1 is now offline
[ 759.522630] smpboot: CPU 2 is now offline
[ 759.550458] smpboot: CPU 3 is now offline
[ 759.583388] smpboot: CPU 4 is now offline
[ 759.606987] smpboot: CPU 5 is now offline
[ 759.625346] smpboot: CPU 6 is now offline
[ 759.653837] smpboot: CPU 7 is now offline
[ 759.655801] PM: Creating hibernation image:
[ 759.682494] PM: Need to copy 90196 pages
[ 759.682497] PM: Normal pages needed: 90196 + 1024, available pages: 433921
[18446744073.256268] PM: Restoring platform NVS memory
[18446744073.257563] Enabling non-boot CPUs ...
[18446744073.257640] x86: Booting SMP configuration:
[18446744073.257640] smpboot: Booting Node 0 Processor 1 APIC 0x1
[18446744073.258291] Disabled fast string operations
[18446744073.258509] cache: parent cpu1 should not be sleeping
[18446744073.258972] CPU1 is up
[18446744073.258998] smpboot: Booting Node 0 Processor 2 APIC 0x2
[18446744073.259670] Disabled fast string operations
[18446744073.259845] cache: parent cpu2 should not be sleeping
[18446744073.260236] CPU2 is up
[18446744073.260272] smpboot: Booting Node 0 Processor 3 APIC 0x3
[18446744073.260877] Disabled fast string operations
[18446744073.261022] cache: parent cpu3 should not be sleeping
[18446744073.261423] CPU3 is up
[18446744073.261443] smpboot: Booting Node 0 Processor 4 APIC 0x4
[18446744073.262117] Disabled fast string operations
[18446744073.262547] cache: parent cpu4 should not be sleeping
[18446744073.263934] CPU4 is up
[18446744073.263991] smpboot: Booting Node 0 Processor 5 APIC 0x5
[18446744073.264913] Disabled fast string operations
[18446744073.265184] cache: parent cpu5 should not be sleeping
[18446744073.265796] CPU5 is up
[18446744073.265821] smpboot: Booting Node 0 Processor 6 APIC 0x6
[18446744073.266459] Disabled fast string operations
[18446744073.266673] cache: parent cpu6 should not be sleeping
[18446744073.267193] CPU6 is up
[18446744073.267219] smpboot: Booting Node 0 Processor 7 APIC 0x7
[18446744073.267894] Disabled fast string operations
[18446744073.268043] cache: parent cpu7 should not be sleeping
[18446744073.268521] CPU7 is up
[18446744073.269975] ACPI: Waking up from system sleep state S4
[18446744073.325536] mptbase: ioc0: pci-resume: pdev=0x0000000010a726cd, slot=0000:00:10.0, Previous operating state [D0]
[18446744073.325631] mptbase: ioc0: pci-resume: ioc-state=0x1,doorbell=0x14000000
[18446744073.325631] mptbase: ioc0: Sending mpt_do_ioc_recovery
[18446744073.325632] mptbase: ioc0: Initiating bringup
[18446744073.325634] [drm] width 640
[18446744073.325639] [drm] height 480
[18446744073.325643] [drm] bpp 32
[18446744073.327033] [drm] Fifo max 0x00040000 min 0x00001000 cap 0x0000077f
[18446744073.327785] [drm] Using command buffers with DMA pool.
[18446744073.328515] usb usb2: root hub lost power or was reset
[18446744073.330434] serial 00:05: activated
[18446744073.331200] usb usb1: root hub lost power or was reset
[18446744073.331518] ehci-pci 0000:02:03.0: cache line size of 64 is not supported
[18446744073.389402] e1000: ens38 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None
[18446744073.423015] ioc0: LSI53C1030 B0: Capabilities={Initiator}
[18446744073.662087] mptbase: ioc0: pci-resume: success
[18446744073.696571] usb 2-2: reset full-speed USB device number 3 using uhci_hcd
[ 0.267194] usb 2-1: reset full-speed USB device number 2 using uhci_hcd
[ 0.433369] PM: Basic memory bitmaps freed
[ 0.433370] OOM killer enabled.
[ 0.433370] Restarting tasks ... done.
[ 0.436577] PM: hibernation exit
PM: hibernation entry 与 PM: hibernation exit 之间就是休眠过程的处理。
有的 PC 上可能出现 BIOS 无法顺利运行,休眠失败的情况,这时可以尝试如下方法:
-
编辑 grub.cfg 内核启动参数中添加用于恢复系统的交换设备 “resume=<交换设备名称>” 如 resume=/dev/sda1
-
执行如下敏玲将休眠设置为 shutdown 模式
echo shutdown > /sys/power/disk
- 进行休眠
echo disk > /sys/power/state
如果恢复系统后系统运行状态有所不同,有时会通过将交换区的数据强制读入内存来改善性能,这可以通过执行如下命令来完成:
swapoff -a
swapon -a
如果休眠失败,可以查看 /var/log/messages 文件来寻找原因。
更多推荐
所有评论(0)