如何在 Linux 上处理 ACPI 事件如何在 Linux 上处理 ACPI 事件如何在 Linux 上处理 ACPI 事件如何在 Linux 上处理 ACPI 事件
  • 文章
  • 正则表达式
    • 工具
  • 登录
找到的结果: {phrase} (显示: {results_count} 共: {results_count_total})
显示: {results_count} 共: {results_count_total}

加载更多搜索结果...

搜索范围
模糊匹配
搜索标题
搜索内容
发表 admin at 2025年2月28日
类别
  • 未分类
标签

如何在 Linux 上处理 ACPI 事件

ACPI是高级配置和电源接口的缩写;作为一项标准,它于 1996 年首次实施,作为 APM(高级电源管理)的后继者。作为一项主要功能,它带来了在操作系统级别处理电源管理的能力,而之前是在 BIOS 中处理的。默认情况下,Linux 上的一些 ACPI 事件是通过 systemd-logind 处理的,但可以通过安装和运行 acpid 服务来实现更复杂的配置。

在本文中,我们了解如何配置 systemd-logind 以及如何通过 acpid 守护进程处理更具体的 ACPI 事件。

在本教程中您将学习:

  • systemd-logind 如何处理某些 ACPI 事件

  • 如何安装并启动acpid服务

  • 如何处理 ACPI 事件

由 systemd-logind 处理的 ACPI 事件

近年来,systemd 已成为 Linux 上的标准 init 系统。经过一些争议之后,几乎所有主要发行版都采用了它,除了一些为了避免它而明确存在的发行版,例如 Debian 衍生品 Devuan。针对 Systemd 的主要批评者之一是它不尊重“做一件事,并做好它”的 Unix 哲学。事实上,随着时间的推移,Systemd 被扩展为执行其他任务,而不仅仅是处理系统初始化,例如管理用户登录:这是通过 systemd-logind 服务完成的。

systemd-logind 服务除其他外还负责创建和管理会话 ID、提供 polkit 访问系统级操作(例如关闭或挂起)以及处理 ACPI 事件(例如电源按钮的行为)。发生此类事件时应执行哪些操作,可以通过编辑 /etc/systemd/logind.conf 文件进行配置。我们来看看它的内容:

[Login]
[...]
#HandlePowerKey=poweroff
#HandleSuspendKey=suspend
#HandleHibernateKey=hibernate
#HandleLidSwitch=suspend
#HandleLidSwitchExternalPower=suspend
#HandleLidSwitchDocked=ignore
#HandleRebootKey=reboot
[...]

为了方便起见,我们截断了文件的输出,以显示最相关的行。默认情况下,文件中的所有行都带有注释,并使用默认值进行报告。报告的指令控制当发生此事件时,systemd-logind 如何处理机器上的电源、挂起、休眠键和盖子开关,例如笔记本电脑。可以分配给指令的一些值是:

  • 忽略

  • 关机

  • 重启

  • 暂停

  • 休眠

  • 混合睡眠

文件中使用的语法非常不言自明:例如,使用 HandlePowerKey=poweroff 行,我们指示 systemd-logind 在按下电源按钮时关闭机器电源,并暂停当按下暂停键时系统将暂停 (HandleSuspendKey=suspend)。同样,我们可以通过使用 ignore 作为相应行的值来忽略特定事件,就像默认情况下对 HandleLidSwitchDocked 所做的那样。

在最常用的桌面环境中,一些可由 systemd-logind 处理的操作由图形电源管理器管理。为了避免冲突或冗余操作,例如按下暂停按钮时系统被暂停两次,此类应用程序禁止 systemd-logind 处理所述事件。

如果我们需要使用更复杂或自定义操作来管理 systemd-logind 未涵盖的 acpi 事件,我们需要更改策略,安装并运行 acpid 守护进程。让我们看看如何进行。

安装 acpid 守护进程

安装 acpid 守护进程非常简单,因为相关软件包包含在主要 Linux 发行版的存储库中。例如,要在 Fedora 上安装该软件包,我们运行以下命令:

$ sudo dnf install acpid

要在 Archlinux 上安装相同的软件包,我们运行:

$ sudo pacman -Sy acpid

最后,在 Debian 和基于 Debian 的发行版上,要安装 acpid 软件包,我们使用 apt 包装器:

$ sudo apt install acpid

安装完成后,我们需要启动acpid服务并在启动时启用它,这样每次启动系统时它都会自动启动。我们可以使用一个命令来执行这两项操作:

$ sudo systemctl enable --now acpid

处理 ACPI 事件

当 acpid 服务运行时,当我们需要配置对特定事件执行的操作时,我们需要做的第一件事就是检查系统如何识别该事件(相同的事件可以在 在不同的机器上有不同的方式:这取决于 ACPI 的实现方式)。 acpi_listen 实用程序专为此特定目的而设计,并作为 acpid 软件包的一部分安装,因此可以随时使用。

为了识别事件,我们需要在终端仿真器中启动该实用程序,触发该事件,并查看 ACPI 如何读取它。让我们看一个实际的例子。假设我们要在笔记本电脑上同时按下 Fn 键和 F3 键时执行操作。首先,我们调用acpi_listen:

$ acpi_listen

我们应该获得一个闪烁的光标;这意味着系统正在等待并准备好显示事件的读取方式。现在我们可以按下组合键。信息立即打印在屏幕上。在这种情况下,在我正在使用的机器上,我得到以下结果:

hotkey ATK0100:00 00000050 00000001

在输出中,我们可以看到四列:第一列代表设备类,第二列是“设备”的内核名称,它出现在/sys/bus/acpi/devices 目录。 第三列报告事件代码。 最后,第四列值根据事件类型具有不同的含义。 一旦我们知道了事件代码,我们就可以将操作与其关联起来。

将事件与操作相关联

将 ACPI 事件与操作关联起来非常容易。它基本上涉及两个文件:第一个是由 acpid 服务解析的文件(默认情况下它必须在 /etc/acpi/events 目录中创建),是我们指定事件代码的地方要处理的脚本以及包含应执行的命令的脚本的路径;第二个是脚本本身。脚本在文件系统中的放置位置因发行版而异。例如,在 Fedora 中,我们默认有以下目录:

├── actions
│   └── power.sh
└── events
├── powerconf
└── videoconf

正如我们已经说过的,/etc/acpi/events 目录包含处理事件的文件。相反,/etc/acpi/actions 目录包含与事件关联的脚本。默认情况下,如您所见,会安装 powerconf 和 power.sh 脚本,它们管理电源按钮的处理。

在 Debian 上,文件的排列方式有所不同。 /etc/acpi/actions 目录不存在:

/etc/acpi
├── events
│   └── powerbtn-acpi-support
└── powerbtn-acpi-support.sh

在 Archlinux 上,事情的处理方式有所不同:默认情况下只有一个文件,其中处理所有事件:/etc/acpi/events/anything:

# Pass all events to our one handler script
event=.*
action=/etc/acpi/handler.sh %e

使文件处理所有事件的是 .* 正则表达式。然后,事件代码作为参数传递给 /etc/acpi/handler.sh 文件(%e 字符串将被事件代码替换)。在脚本中,根据 case 语句中的后者来选择要执行的操作。

然而,文件的排列方式并不那么重要。它不会改变事情的运作方式。让我们来管理我们之前讨论过的事件:由于我正在使用的机器上不存在休眠键,因此我将使得当按下 Fn+f3 组合键时,系统将被置于进入冬眠状态。首先,我们创建事件文件,我们将其命名为 hibernateconf;它只包含两行:

event=hotkey ATK0100:00 00000050
action=/etc/acpi/actions/hibernate.sh

在第一行中,我们将事件代码指定为 event 的值:在本例中,我们仅使用通过 acpi_listen 实用程序发现的文字代码。在第二行中,我们指定应执行的脚本路径:/etc/acpi/actions/hibernate.sh。

要记住的一件重要事情是,如果使用 SELinux(在 Fedora 上默认处于活动状态),我们必须确保“事件”文件具有与其关联的适当上下文,否则该事件将不会被处理。要了解应将什么上下文应用于该文件,我们可以查看 /etc/acpi/events 目录中的现有文件作为参考。我们所要做的就是使用 -Z 选项运行 ls:

$ ls -lZ /etc/acpi/events
-rw-r--r--. 1 root root system_u:object_r:etc_t:s0 168 Oct 5 21:27 powerconf
-rw-r--r--. 1 root root system_u:object_r:etc_t:s0 236 Oct 5 21:27 videoconf

我们可以看到,在 Fedora 上,/etc/acpi/events 目录中的两个现有文件具有 system_u:object_r:etc_t 上下文。要将相同的上下文应用于我们的 hibernateconf 文件,我们可以使用它们作为 chcon 命令的参考:

$ sudo chcon --reference /etc/acpi/events/powerconf /etc/acpi/events/hibernateconf

事件文件调用的脚本将包含以下行:

#!/bin/bash
systemctl hibernate

在脚本中,我们只需使用 systemctl 来休眠系统。剩下要做的就是使脚本可执行:

$ sudo chmod +x /etc/acpi/actions/hibernate.sh

为了使新配置生效,我们需要重新启动 acpid 守护进程:

$ sudo systemctl restart acpid.service

当我们按下Fn+F3时,系统现在应该处于休眠状态。

结论

在本文中,我们了解了如何在 Linux 上处理 ACPI 事件。我们看到了按下电源按钮、暂停键和关闭笔记本电脑盖子等基本事件是如何由 systemd-logind 管理的,并且可以通过 /etc/systemd/logind.conf 文件进行配置。我们还了解了如何通过在一些最常用的 Linux 发行版上安装 acpid 守护进程来处理自定义事件。

©2015-2025 艾丽卡 support@alaica.com