# Power management (简体中文)

From ArchWiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

相关文章

- Power management/Suspend and hibernate
- Display Power Management Signaling
- CPU frequency scaling
- Hybrid graphics
- Kernel modules
- sysctl
- udev

翻译状态：本文是 Power management 的翻译。上次翻译日期：2017-11-15。如果英文版本有所更改，则您可以帮助同步翻译。

电源管理这个功能可以在系统组件不工作时切断其电源或将其切换到低耗电模式。

Arch 中的电源管理包含两个主要部分：

1. 配置与硬件交互的内核
   - Kernel parameters
   - Kernel modules
   - udev rules
2. 配置用户空间工具，这些工具与内核交互，很多用户空间的工具，配置界面更友好。

## 用户空间工具

使用这些工具可以简化配置，因为它们的工作方式基本类似，所以请勿同时运行多个程序，以避免冲突。更多电源管理选型请参考 power management category。下面是一些比较流行的省电工具

### 命令行工具

- aclidswitch — 简单的电源管理工具，可以根据笔记本是否交流供电定制屏幕翻转、亮度和省电模式。

  https://github.com/orschiro/aclidswitch || aclidswitch-gitAUR[断开的链接：package not found]

- acpid — 一个支持 netlink 的 ACPI 电源管理事件分发进程。

  https://sourceforge.net/projects/acpid2/ || acpid

- Laptop Mode Tools — 配置笔记本电源设置的工具，很多人将其视为省电标准工具，需要的配置比较多。

  https://github.com/rickysarraf/laptop-mode-tools || laptop-mode-toolsAUR

- powertop — 检查电源消耗和电源管理的工具，可以协助省电模式的配置。

  https://01.org/powertop/ || powertop

- systemd — 一个系统和服务管理器。

  https://freedesktop.org/wiki/Software/systemd/ || systemd

- TLP — Linux 高级电源管理

  https://linrunner.de/tlp || tlp

### 图形化界面

- batterymon-clone — 简单的电池监视器。

  https://github.com/jareksed/batterymon-clone || batterymon-cloneAUR

- batsignal — 轻量级电池监视器，使用libnotify来警告电池电量不足。

  https://github.com/electrickite/batsignal || batsignalAUR

- cbatticon — 一款在系统托盘中的轻量且快速的电池图标。

  https://github.com/valr/cbatticon || cbatticon

- GNOME Power Statistics — GNOME的电源信息统计工具。

  https://gitlab.gnome.org/GNOME/gnome-power-manager || gnome-power-manager

- KDE Power Devil — Plasma的电源管理模块。

  https://invent.kde.org/plasma/powerdevil || powerdevil

- LXQt Power Management — LXQt的电源管理模块。

  https://github.com/lxqt/lxqt-powermanagement || lxqt-powermanagement

- MATE Power Management — MATE的电源管理工具。

  https://github.com/mate-desktop/mate-power-manager || mate-power-manager

- MATE Power Statistics — MATE的电源信息统计工具。

  https://github.com/mate-desktop/mate-power-manager || mate-power-manager

- powerkit — 一个独立于桌面的轻量级全功能电源管理器。

  https://github.com/rodlie/powerkit || powerkitAUR

- Xfce Power Manager — Xfce的电源管理工具。

  https://docs.xfce.org/xfce/xfce4-power-manager/start || xfce4-power-manager

- vattery — 用Vala编写的电池监控应用程序，它将在系统托盘中显示笔记本电脑电池的状态。

  https://www.jezra.net/projects/vattery.html || vatteryAUR

## 用 systemd 进行电源管理

### ACPI 事件

systemd 能够处理某些电源相关的 ACPI 事件，通过 `/etc/systemd/logind.conf` 或 `/etc/systemd/logind.conf.d/*.conf` 进行配置，请参考 logind.conf(5). 如果系统没有专门的电源管理程序，systemd 可以替换掉原本用来响应这些 ACPI 事件的 acpid。

事件的动作可以是 `ignore`, `poweroff`, `reboot`, `halt`, `suspend`, `hibernate`, `hybrid-sleep`, `lock` 或 `kexec`. 休眠或挂起动作需要被正确 设置. 如果没有配置事件动作，systemd 会使用默认动作。

事件处理程序 | 描述 | 默认动作
--- | --- | ---
`HandlePowerKey` | 按下电源键后的动作 | `poweroff`
`HandleSuspendKey` | 按下挂起键后的动作 | `suspend`
`HandleHibernateKey` | 按下休眠键后触发的动作 | `hibernate`
`HandleLidSwitch` | 笔记本翻盖后触发的动作，除了下面的情况 | `suspend`
`HandleLidSwitchDocked` | 如果笔记本放到了扩展坞或连接了多个显示器时，笔记本翻盖合上时触发的动作 | `ignore`

修改后需要运行 `systemctl restart systemd-logind` 使上述更改生效。

注意： systemd 无法处理交流电源和电池 ACPI 事件，所以还得使用 Laptop Mode Tools 或 acpid 工具。

#### 电源管理器

有些 桌面环境 包含的电源管理器会 禁用(临时关闭) 某些或全部 systemd ACPI 设置。这些电源管理器运行时，请在它们的设置中配置 ACPI 事件的动作，只有不被禁用的事件才能在 `/etc/systemd/logind.conf` 或 `/etc/systemd/logind.conf.d/*.conf` 中配置。

如果电源管理器没有禁用 systemd 的事件动作，可能出现 systemd 挂起了系统，然后当系统被唤醒之后，电源管理器又再次将系统挂起的情况。截止到 2016 年 12 月，KDE, GNOME, Xfce 和 MATE 的电源管理器会执行需要的禁用命令。在使用 acpid 或其它程序处理 ACPI 事件时，响应的 systemd 动作没有被禁用，可以将 `Handle` 设置为 `ignore`. 请参考 systemd-inhibit(1).

#### xss-lock

xss-lock-gitAUR 订阅 systemd 的 `suspend`, `hibernate`, `lock-session` 和 `unlock-session` 事件，并执行对应的动作(运行屏幕锁定并等待用户解锁或停止锁定). xss-lock 还会响应 DPMS 事件并执行屏幕锁定和解锁动作。

下面命令可以 自动启动 xss-lock:

    xss-lock -- i3lock -n -i background_image.png &

### 休眠和挂起

systemd 提供了挂起到内存，挂起到硬盘和混合休眠命令，使用内核的原生挂起和休眠功能执行响应的动作。systemd 还提供了在休眠前和唤醒后执行自定义动作的机制。除了内核默认的待机支持后端，systemd 也可以使用其他后端（比如 Uswsusp 或 TuxOnIce[archived page]）。

`systemctl suspend` 应该不许要额外的配置，要使用 `systemctl hibernate`，需要先按照 Suspend and hibernate#Hibernation 进行设置。

#### 混合休眠

`systemctl hybrid-sleep` 同时执行休眠和挂起，这样如果计算机突然断电(交流电源被拔掉或电池耗尽)，将会从硬盘休眠中恢复。如果没有断电，将从内存挂起中恢复，速度比从硬盘恢复快。因为 "hybrid-sleep" 需要将内存转存到交换空间，所以进入睡眠的时间比 `systemctl suspend` 慢。另外一个选择是使用延迟休眠功能。

### 休眠钩子

systemd 提供了两种类似的待机/休眠时执行脚本的机制。

#### 使用服务文件

可以将服务文件附在 suspend.target、hibernate.target 或 sleep.target 中，这样就能在待机/休眠前后执行某些操作。用户级操作和root/系统级操作应该使用不同的服务文件。要启用用户级服务文件，使用 `# systemctl enable suspend@<用户名> && systemctl enable resume@<用户名>`。例如：

    /etc/systemd/system/suspend@.service

    [Unit]
    Description=User suspend actions
    Before=sleep.target

    [Service]
    User=%I
    Type=forking
    Environment=DISPLAY=:0
    ExecStartPre= -/usr/bin/pkill -u %u unison ; /usr/local/bin/music.sh stop ; /usr/bin/mysql -e 'slave stop'
    ExecStart=/usr/bin/sflock
    ExecStartPost=/usr/bin/sleep 1

    [Install]
    WantedBy=sleep.target

    /etc/systemd/system/resume@.service

    [Unit]
    Description=User resume actions
    After=suspend.target

    [Service]
    User=%I
    Type=simple
    ExecStartPre=/usr/local/bin/ssh-connect.sh
    ExecStart=/usr/bin/mysql -e 'slave start'

    [Install]
    WantedBy=suspend.target

注意： As screen lockers may return before the screen is "locked", the screen may flash on resuming from suspend. Adding a small delay via `ExecStartPost=/usr/bin/sleep 1` helps prevent this.

root/系统级服，使用 `root-suspend` 或 `root-resume` 激活：

    /etc/systemd/system/root-resume.service

    [Unit]
    Description=Local system resume actions
    After=suspend.target

    [Service]
    Type=simple
    ExecStart=/usr/bin/systemctl restart mnt-media.automount

    [Install]
    WantedBy=suspend.target

    /etc/systemd/system/root-suspend.service

    [Unit]
    Description=Local system suspend actions
    Before=sleep.target

    [Service]
    Type=simple
    ExecStart=-/usr/bin/pkill sshfs

    [Install]
    WantedBy=sleep.target

上述服务文件的一些解释（详见 systemd.service(5)）：

- 如果设置 `Type=OneShot`，那么可以使用多个 `ExecStart=` 参数。否则只能写一个，替代方案是在 `ExecStartPre` 中添加命令，或使用分号分隔不同命令（见第一个例子，分号前后的空格都是必须的）。
- 若命令前加上一个“-”（半角减号），则命令返回非零值时会被忽略、当作正常执行处理。
- 有关调试，最好的方法是用 `journalctl` 查看日志。

#### 合并待机和唤醒服务文件

利用下面这种自定义的一体化待机和唤醒服务，使用单一的钩子扩展即可对不同操作（待机/休眠/混合休眠）的不同阶段（进入/唤醒）进行控制。

例子和解释：

    /etc/systemd/system/wicd-sleep.service

    [Unit]
    Description=Wicd sleep hook
    Before=sleep.target
    StopWhenUnneeded=yes

    [Service]
    Type=oneshot
    RemainAfterExit=yes
    ExecStart=-/usr/share/wicd/daemon/suspend.py
    ExecStop=-/usr/share/wicd/daemon/autoconnect.py

    [Install]
    WantedBy=sleep.target

- `RemainAfterExit=yes`：服务启动后，除非显式地停止，否则就认为是活动的。
- `StopWhenUnneeded=yes`：服务活动时，如果无其他服务依赖该服务，就停止它。在本例中，该服务会在 sleep.target 停止后停止活动。
- 由于 sleep.target 会被 suspend.target、hibernate.target、hybrid-sleep.target 调用，且 sleep.target 本身设置了 StopWhenUnneeded，该服务文件对以上各种操作都是有效的。

#### 延迟休眠服务文件

An alternative approach is delayed hibernation. This makes use of sleep hooks to suspend as usual but sets a timer to wake up later to perform hibernation. Here, entering sleep is faster than `systemctl hybrid-sleep` since no hibernation is performed initially. However, unlike "hybrid-sleep", at this point there is no protection against power loss via hibernation while in suspension. This caveat makes this approach more suitable for laptops than desktops. Since hibernation is delayed, the laptop battery is only used during suspension and to trigger the eventual hibernation. This uses less power over the long-term than a "hybrid-sleep" which will remain suspended until the battery is drained. Note that if your laptop has a spinning hard disk, when it wakes up from suspend in order to hibernate, you may not want to be moving or carrying the laptop for these few seconds. Delayed hibernation may be desirable both to reduce power use as well as for security reasons (e.g. when using full disk encryption). An example script is located here. See also this post for an updated systemd sleep hook.

A slightly updated version of the service is:

    /etc/systemd/system/suspend-to-hibernate.service

    [Unit]
    Description=Delayed hibernation trigger
    Documentation=https://bbs.archlinux.org/viewtopic.php?pid=1420279#p1420279
    Documentation=https://wiki.archlinux.org/index.php/Power_management
    Conflicts=hibernate.target hybrid-sleep.target
    Before=sleep.target
    StopWhenUnneeded=true

    [Service]
    Type=oneshot
    RemainAfterExit=yes
    Environment="WAKEALARM=/sys/class/rtc/rtc0/wakealarm"
    Environment="SLEEPLENGTH=+2hour"
    ExecStart=-/usr/bin/sh -c 'echo -n "alarm set for "; date +%%s -d$SLEEPLENGTH | tee $WAKEALARM'
    ExecStop=-/usr/bin/sh -c '\
      alarm=$(cat $WAKEALARM); \
      now=$(date +%%s); \
      if [ -z "$alarm" ] || [ "$now" -ge "$alarm" ]; then \
         echo "hibernate triggered"; \
         systemctl hibernate; \
      else \
         echo "normal wakeup"; \
      fi; \
      echo 0 > $WAKEALARM; \
    '

    [Install]
    WantedBy=sleep.target

The `Before` and `Conflicts` options ensure it only is run for suspension and not hibernation--otherwise the service will run twice if delayed hibernation is triggered. The `WantedBy` and `StopWhenUnneeded` options are so it is started before sleep and stops upon resume. (Note that the `suspend.target` and `hibernate.target` targets do not stop when unneeded, but `sleep.target` does). Enable the service.

##### 使用 /usr/lib/systemd/system-sleep 钩子

systemd 在待机/休眠时执行 `/usr/lib/systemd/system-sleep/` 里的所有脚本，传递下面两个参数：

- 参数1：若是准备进入待机/休眠状态，则为 `pre`；唤醒时为 `post`。
- 参数2：事件名称，`suspend`，`hibernate` 或 `hybrid-sleep`。

systemd 会同时执行所有脚本。

脚本输出会记录在相关服务（`systemd-suspend.service`、`systemd-hibernate.service` 或 `systemd-hybrid-sleep.service`）中。通过日志[断开的链接：无效的部分]查看：

    # journalctl -b -u systemd-suspend

注意： 除了使用自定义脚本，还可以利用 `sleep.target`、`suspend.target`、`hibernate.target` 或 `hybrid-sleep.target` 来为单元（unit）添加睡眠状态策略。

脚本示范：

    /usr/lib/systemd/system-sleep/example.sh

    #!/bin/sh
    case $1/$2 in
      pre/*)
        echo "进入 $2 状态..."
        ;;
      post/*)
        echo "从 $2 状态唤醒..."
        ;;
    esac

记得添加可执行权限：

1. chmod a+x /usr/lib/systemd/system-sleep/example.sh

详情参见 systemd.special(7) 和 systemd-sleep(8)。

Category:

- Power management (简体中文)

Hidden categories:

- Pages with broken package links
- Pages with links to archived pages
- Pages with broken section links