電源管理/喚醒觸發器 - 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]。

分類：​

- 電源管理
- 筆記本電腦

電源管理/喚醒觸發器
新增話題