电源管理/唤醒触发器 - Arch Linux 中文维基

跳转到内容

# 电源管理/唤醒触发器

来自 Arch Linux 中文维基
< 电源管理

相关文章

- Wake-on-LAN
- 笔记本电脑

唤醒触发器是可以将系统从任何硬件节能状态唤醒的事件源。显而易见的例子是电源或挂起按钮、网络唤醒（英语：Wake-on-LAN）功能或笔记本电脑系统中的盖开关。唤醒触发器可以通过下面列出的各种内核接口进行控制。没有涵盖所有可能的触发器的统一接口。

## 唤醒触发器接口

### /proc/acpi/wakeup

读取 `/proc/acpi/wakeup` 文件将生成 ACPI 注册的唤醒源列表，其中包含相应的 `sysfs` IDs（如果可用）。将条目从设备列写入文件可切换其状态。例如，要禁用打开笔记本电脑盖时的唤醒功能，请运行：

    # echo "LID" > /proc/acpi/wakeup

### /sys/module/acpi/parameters/ec_no_wakeup

该文件表示 ACPI 内核模块选项 `ec_no_wakeup` 的值，当系统处于挂起到空闲（`s2idle`）电源状态时，该选项控制从嵌入式控制器传递唤醒触发器[1]。在现代笔记本电脑上，嵌入式控制器唤醒在某些（英语：Lenovo ThinkPad Helix 2nd Gen#Disable embedded-controller wake-ups）情况下会导致电池过度消耗。

### /sys/devices/

每个支持唤醒的 `sysfs` 设备都在设备的 `power` 子目录中包含文件 `wakeup`。该文件包含唤醒触发器的状态，也可以写入。总线控制器和端点设备能够唤醒系统。例如，若要禁用第一个 USB 控制器（总线）的唤醒，请运行：

    # echo "disabled" > /sys/bus/usb/devices/usb1/power/wakeup

如果启用了触发器，端点设备应该能够唤醒设备，而不管控制器的设置如何，但这可能与依赖于硬件。

编写 PowerTOP 与 `sysfs` 的接口，但它只通过读取 `/sys/class/net/` 和 `/sys/bus/usb/devices/`（包括到 `/sys/devices/` 的符号链接）来列出网络和 USB 设备的唤醒触发器。

### /sys/class/wakeup/*

几乎所有的唤醒触发器都可以在 `/sys/class/wakeup` 目录中找到，该目录包含指向所有相关设备的符号链接。这对于通过子目录查找可能的唤醒触发器非常有用。一些触发器可以对应于虚拟设备，而与硬件相关的唤醒触发器至少包含以下文件之一：

    /sys/class/wakeup/*/device/physical_node/power/wakeup
    /sys/class/wakeup/*/device/power/wakeup

`/sys/class/wakeup` 中的一些唤醒触发器还提供了一个以下文件指向所在位置隐藏的 `/proc/acpi/wakeup` 名称的链接：

    /sys/class/wakeup/*/device/path

## 持久设置

原先的方法应该足以设置 `/proc/acpi/wakeup` 状态和 `acpi.ec_no_wakeups` 内核参数，而 udev 的事件驱动途径是配置 `sysfs` 设备的可靠方式。

### 使用 systemd 的原先方法

`ec_no_wakeups` ACPI 内核模块选项可以在启动时设置，如本文所述。在引导时设置 `sysfs` 值的标准解决方案是 systemd services，例如在此故障排除中。`/proc/acpi/wakeup` 的另一个基于 systemd 的管理器是 wakeup-triggersAUR。

一些系统可以在电源状态转换时覆盖一些 ACPI 唤醒触发器，这更像是一个 bug，而不是一个功能。如果硬件能在可预测的时间覆盖触发器，则仍然可以使用适当构建的 systemd units 来解决。`sleep.target` 是一个通用目标，涵盖所有不同的挂起状态，在这种情况下可能会有所帮助，但没有通用的 `wakeup.target` [2]。

此方法仅适用于始终连接的 `sysfs` 设备。

### 使用 udev 的事件驱动

使用 udev 规则设置唤醒触发器状态是一种事件驱动的方法，在连接具有唤醒触发器的设备时都能可靠地工作。关键是检测规则中是否添加了新设备（ `ACTION=="add"`），并将唤醒触发器状态设置为 `ATTR{power/wakeup}="disabled"`。如果硬件正在重置此设置，udev 可以尝试在每次设备更改时重新应用规则来规避此设置（`ACTION=="add|change"`）。通过 `udevadm info -q all -a /sys/devices/...` 可以获得一个设备树，其中包含用于匹配 `sysfs` 中找到的特定设备的可能参数。

这里一个典型的常见例子是罗技统一 USB 接收器。它的唤醒触发器应该在默认情况下启用，如果不需要，解决方案可以是 udev 规则，如下所示:

    /etc/udev/rules.d/logitech-unifying.rules

    ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c52b", ATTR{power/wakeup}="disabled"

在 udev 文章中描述了启用必要触发器的相反情况。

udev 触发器在设备枚举中出现得太早，以至于使用上述方法禁用唤醒触发器会导致（某些？）禁用的触发器不在 `/sys/class/wakeup` 中列出。这可能取决于设备在启动时是否已经存在，需要进一步阐明。

## 疑难解答

### 列出设备和/或总线树

当试图理解某个系统的所有唤醒触发器时，这些辅助命令会很有用，有助于编写 udev 规则或进行常见的唤醒源故障排除：

    # lshw -businfo -numeric
    # lspci -DPPnn
    # lsusb -tvv

### 挂起后被立即唤醒

对于某些带有 LynxPoint 或 LynxPoint-LP 芯片组的 Intel Haswell 系统，有报告称它们会在挂起后就立即被唤醒。这与错误的 BIOS ACPI 实现，以及 `xhci_hcd` 如何在引导期间如何解释它们都有关。作为一项解决方案，内核会将报告的受影响系统逐个添加到拒绝列表（名为 `XHCI_SPURIOUS_WAKEUP`）[3]。

电脑也有可能在其它情况下发生立即恢复，比如，一个 USB 设备在挂起后插入，且启动了 ACPI 唤醒触发器。对于这样的情况，如果受影响的系统尚未被加入上述拒绝列表，一个可行的方案是禁用相关的唤醒触发器。通过 USB 禁用唤醒的例子见后[4]。

要查看当前配置：

    $ cat /proc/acpi/wakeup

    Device  S-state   Status   Sysfs node
    ...
    EHC1      S3    *enabled  pci:0000:00:1d.0
    EHC2      S3    *enabled  pci:0000:00:1a.0
    XHC       S3    *enabled  pci:0000:00:14.0
    ...

可以看到相关的设备有 `EHC1`、`EHC2` 和 `XHC`（USB 3.0设备）。要切换它们的状态，你需要以 root 权限把设备名写入到文件里。

    # echo EHC1 > /proc/acpi/wakeup
    # echo EHC2 > /proc/acpi/wakeup
    # echo XHC > /proc/acpi/wakeup

这能使挂起重新工作。但是，此设置只是临时的，需要在每次启动时设置。要实现自动化，请参阅 Systemd#临时文件或论坛帖子以了解可能的解决方案。

#### nouveau 驱动程序

如果使用了 nouveau 驱动程序，则立即唤醒的原因可能是驱动程序中的错误，这有时会阻止 GPU 挂起。一种可能的解决方法是在休眠前卸载 `nouveau` 内核模块，并在唤醒后重新加载。为此，请创建以下脚本：

    /usr/lib/systemd/system-sleep/10-nouveau.sh

    #!/bin/bash

    case $1/$2 in
      pre/*)
        # echo "进入 $2 状态..."
        /usr/bin/echo "0" > /sys/class/vtconsole/vtcon1/bind
        /usr/bin/rmmod nouveau
        ;;
      post/*)
        # echo "从 $2 状态唤醒..."
        /usr/bin/modprobe nouveau
        /usr/bin/echo "1" > /sys/class/vtconsole/vtcon1/bind
        ;;
    esac

第一个 echo 行将 `nouveaufb` 从帧缓冲控制台驱动程序（`fbcon`）中解除绑定。通常它是 `vtcon1`，如本例所示，但也可能是另一个 `vtcon*`。查看 `/sys/class/vtconsole/vtcon*/name` 其中哪一个是 frame buffer device [5]。

分类：​

- 电源管理
- 笔记本电脑

电源管理/唤醒触发器
添加话题