电源管理/挂起与休眠
有多种方法可用于挂起,特别是:
- Suspend to idle(挂起到空闲状态)
- 英特尔称之为 S0ix,微软称之为现代待机(以前是“保持网络连接的待机”),内核称之为 S2Idle。设计用于替代 S3 睡眠状态的支持系统,提供相同的节能,但大大减少了唤醒时间。
- Suspend to RAM(挂起到内存,通称挂起)
- ACPI 定义的 S3 睡眠状态。通过将机器中大多数和 RAM 不相关的部件断电来工作,RAM 是恢复机器状态所必需的。由于可以节省大量电力,建议笔记本电脑在使用电池运行且盖子关闭时(或用户在一段时间内处于非活动状态)自动进入此模式。
- Suspend to disk(挂起到硬盘,通称休眠)
- ACPI 定义的 S4 睡眠状态。将机器状态保存到交换空间并关闭机器。再次开机后,恢复状态。直到开机前,机器都不会有任何待机功耗。
- Hybrid suspend(混合挂起)
- 挂起和休眠的混合,有时称为挂起到两者。将机器状态保存到交换空间,但并不关闭电脑,而是调用默认的挂起机制,从而使未掉电的电脑能立刻恢复。如果电脑掉电(断电且电池耗尽),系统也可以从硬盘的交换空间中恢复,尽管比从内存中恢复慢一些。
以上三者均由内核提供基础功能,再由高级接口进行了一定调整,以适配一些较为复杂的硬件与内核模块(如显卡唤醒后的重新初始化)
内核接口 (swsusp)[编辑 | 编辑源代码]
可以通过直接告知内核中的软件挂起代码(swsusp)进入挂起状态,具体的方法和状态取决于硬件支持的程度。在现代内核中,向 /sys/power/state
写入特定字符串是触发此挂起的主要机制。
更多信息详见内核文档。
高级接口 (systemd)[编辑 | 编辑源代码]
systemd 提供了用于挂起、休眠和混合挂起的原生命令。这是 Arch Linux 中使用的默认接口。
systemctl suspend
开箱即用。要使 systemctl hibernate
在您的系统上运行,您可能需要遵循 #休眠 中的说明。
还有两种结合挂起和休眠的模式:
systemctl hybrid-sleep
将系统同时挂起到 RAM 和磁盘,因此完全断电不会导致数据丢失。 此模式也称为“同时挂起”。
systemctl suspend-then-hibernate
最初会尽可能将系统挂起到 RAM 中,然后使用 RTC 警报将其唤醒并休眠。RTC 警报由 systemd-sleep.conf(5) 中的HibernateDelaySec
设置。默认值通过估计电池放电率来设置,以使系统保持 5% 的电池电量,或者在没有电池的情况下保持两小时。 估计值是根据 systemd-sleep.conf(5) 中SuspendEstimationSec
指定的时间后电池电量变化获得的,该系统将短暂唤醒进行测量(如果系统从挂起中手动唤醒,也会进行测量)。
关于配置睡眠或休眠钩子,详见电源管理#睡眠钩子。又见 systemctl(1)、systemd-sleep(8) 和 systemd.special(7)。
更改挂起方法[编辑 | 编辑源代码]
在 S0ix 挂起不能提供与常规 S3 睡眠相同的节能的系统上,或者当节能优于快速的恢复时间时,可以更改默认挂起方法。
运行以下命令以查看硬件公开支持的所有挂起方法(当前方法包裹在方括号中显示[2]):
$ cat /sys/power/mem_sleep
[s2idle] shallow deep
mem_sleep 字符串 | 睡眠状态 |
---|---|
s2idle | suspend-to-idle |
shallow | standby |
deep | suspend-to-RAM |
如果您的硬件没有公布 deep
睡眠状态,请首先检查 UEFI 是否公布了它的某些设置,通常是在“电源(Power)”或“睡眠状态(Sleep state)”或类似的用词下,并使用名为 Windows 10, Windows and Linux 或 S3/Modern standby support 关于 S0ix 的选项,以及 Legacy, Linux, Linux S3 或 S3 enabled 关于 S3 睡眠的选项。否则,您可以继续使用 s2idle
,考虑使用休眠或尝试给 DSDT 表打补丁(或在线查找补丁版本)。
通过在更改睡眠方法后测试几个睡眠周期,验证你的硬件没有 S3 睡眠问题:
# echo deep > /sys/power/mem_sleep
如果没有发现任何问题,可以通过 systemd-sleep.conf(5) 中的 MemorySleepMode
选项使更改永久化。
/etc/systemd/sleep.conf.d/mem-deep.conf
[Sleep] MemorySleepMode=deep
或者通过mem_sleep_default=deep
内核参数。
在一些相反的情况下,有缺陷的固件公布支持 deep
睡眠,但只支持 s2idle
。在这种情况下,通过选项中的 SuspendState
可以以另一种方法使用 s2idle
:
/etc/systemd/sleep.conf.d/freeze.conf
[Sleep] SuspendState=freeze
休眠[编辑 | 编辑源代码]
为了使用休眠功能,您必须创建一个 swap 分区或文件、#配置 initramfs 以便在早期用户空间启动恢复过程,并指定交换空间的位置以便 initramfs 可以访问,例如:由 systemd 定义的 HibernateLocation
EFI 变量或 resume=
内核参数。下面详细描述了这三个步骤。
- 使用 encryption 时,请参阅 dm-crypt/Swap encryption#With suspend-to-disk support。
- linux-hardened包 不支持休眠,请参阅 FS#63648。
- 即使 zram 配置了永久存储上的后端设备,也不支持休眠到 zram 上的交换分区。虽然 logind 会阻止尝试将休眠到 zram 上的交换空间,但作为替代,您可以创建多个交换空间。内存将存储到交换文件中,而另一个可用交换空间将保留给 zram。有关详细信息,请参阅 #Maintaining swap file for hibernation with zram。
swap分区/文件的大小[编辑 | 编辑源代码]
即使swap比内存小,成功休眠的可能性仍然不小。参见内核文档中的“image_size”部分以获取关于 image_size
sysfs(5) pseudo-file 的更多信息。
您可以减小 /sys/power/image_size
的设定值以使休眠镜像尽可能小(对于小交换分区),或者增大它以加快休眠过程(也许)。对于 RAM 很大的系统,较小的值可能会显著提高系统从休眠中恢复的速度。这是一个临时文件,参阅Systemd#临时文件以固定你的修改。
/etc/tmpfiles.d/hibernation_image_size.conf
# Path Mode UID GID Age Argument w /sys/power/image_size - - - - 0
休眠镜像不能跨多个交换分区和/或交换文件。它必须完全适配一个交换分区或一个交换文件[4]
配置 initramfs[编辑 | 编辑源代码]
- 当使用一个 busybox-based 的 initramfs 时(这是默认值),
/etc/mkinitcpio.conf
中需要resume
钩子。无论是通过卷标还是通过 UUID,交换分区都是通过 udev 设备节点来引用的,因此resume
钩子必须在udev
钩子之后。这是一个使用默认钩子配置的示例:
HOOKS=(base udev autodetect keyboard microcode modconf kms keyboard keymap consolefont block filesystems resume fsck)
- 编辑后记得重新生成 initramfs。
- 当使用带有
systemd
钩子的 initramfs 时,已经提供了恢复机制,不需要额外添加钩子。
传递休眠位置到 initramfs[编辑 | 编辑源代码]
当系统休眠时,内存映像被转储到交换空间,其中也包括挂载文件系统的状态。因此,休眠位置必须提供给 initramfs,即在挂载根文件系统之前,以便从休眠状态恢复。
从 systemd包 v255 和 mkinitcpio包 v38 开始,当系统运行在 UEFI 上时,systemd-sleep(8) 将自动选择合适的交换空间进行休眠,并且所用交换空间的信息存储在 HibernateLocation
EFI 变量中。在下次启动时,systemd-hibernate-resume(8) 从 EFI 变量读取位置,系统恢复。这意味着除非系统使用遗留 BIOS 或您想选择与自动选择的不同的交换空间,否则以下步骤不是必需的。
手动指定休眠位置[编辑 | 编辑源代码]
可以传递内核参数 resume=swap_device
。其中 swap_device 遵循 persistent block device naming。例如:
resume=UUID=4209c845-f495-4c43-8a03-5363dd433153
resume="PARTLABEL=swap分区卷标"
resume=/dev/archVolumeGroup/archLogicalVolume
——如果swap在LVM逻辑卷上(UUID 和 标签应该同样可以工作)
内核参数只有在重新启动后才会生效。要想不重启而马上休眠,请从lsblk获取卷的主要和次要设备号,并 echo major:minor
到/sys/power/resume
。
例如,如果交换设备是8:3
:
# echo 8:3 > /sys/power/resume
如果使用交换文件,请继续查看#获取交换文件偏移量。
获取交换文件偏移量[编辑 | 编辑源代码]
使用交换文件进行休眠时,文件系统所在的块设备应该在 resume=
中指定,并且还需要通过 resume_offset=
内核参数 指定交换文件的物理偏移量。 [5]
在除 Btrfs 之外的文件系统上,可以通过运行 filefrag -v 交换文件
来获取 resume_offset=
的值。输出为表格格式,所需的值位于第一行 physical_offset
列中。
例如:
# filefrag -v /swapfile
Filesystem type is: ef53 File size of /swapfile is 4294967296 (1048576 blocks of 4096 bytes) ext: logical_offset: physical_offset: length: expected: flags: 0: 0.. 0: 38912.. 38912: 1: 1: 1.. 22527: 38913.. 61439: 22527: unwritten 2: 22528.. 53247: 899072.. 929791: 30720: 61440: unwritten ...
在本例中,resume_offset=
的值是首先出现的那个 38912
。
Alternatively, to directly acquire the offset value:
# filefrag -v swap_file | awk '$1=="0:" {print substr($4, 1, length($4)-2)}'
For Btrfs, do not try to use the filefrag tool, since the "physical" offset you get from filefrag is not the real physical offset on disk; there is a virtual disk address space in order to support multiple devices.[6] Instead, use the btrfs-inspect-internal(8) command. E.g.:
# btrfs inspect-internal map-swapfile -r swap_file
198122980
In this example, the kernel parameter would be resume_offset=198122980
.
To apply the change immediately (without rebooting), echo the resume offset to /sys/power/resume_offset
. For example, if the offset is 38912
:
# echo 38912 > /sys/power/resume_offset
findmnt -no UUID -T swap_file
resume
parameter must point to the unlocked/mapped device that contains the file system with the swap file.不要尝试使用 filefrag 工具,在 Btrfs 上,从 filefrag 获得的 physical_offset 不是实际 offset。因为 btrfs 有一个虚拟磁盘地址空间以支持多个设备。[7]
自 btrfs-progs包 6.1,提供了一个命令来检查用于休眠的交换文件及其偏移值。参见 btrfs-inspect-internal(8)。
# btrfs inspect-internal map-swapfile -r path/to/swapfile
198122980
Maintaining swap file for hibernation with zram[编辑 | 编辑源代码]
It is possible to solve the hibernation problem with zram RAM-only swap by maintaining two or more swap spaces at the same time. systemd will always ignore zram block devices before triggering hibernation [8], therefore keeping both spaces enabled should work without further intervention.
After configured the swap file, follow the zram page. Make sure zram has the higher swap priority (e.g. pri=100
).
- Do not create an on-demand swap unit for hibernation as it is not officially supported. See systemd issues #16708 and #30083.
- The kernel alone is responsible for reclaiming anonymous memory of pages and swapping them; not using a swap space can actually lead to bad memory usage. The user can manage priorities in reclaiming memory for certain applications in the form of
memory.low
, tunable by control groups. Overall this is more effective than setting the swappiness parameter. - Read the Swap Management in kernel documentation and the Chris Down's article - In defence of swap: common misconceptions for more details.
休眠到精简配置的LVM卷中[编辑 | 编辑源代码]
在精简配置的LVM卷中休眠是可能的,但必须确保该卷已完全分配。否则系统将无法从中恢复,参见 FS#50703。
可以通过简单地用零填充来完全分配LVM卷。例如:
# dd if=/dev/zero of=/dev/vg0/swap bs=1M status=progress
想确认卷是否已完全被分配,使用:
# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert swap vg0 Vwi-aot--- 10.00g pool 100
完全分配的卷将显示为具有100%的Data%
/etc/fstab
使用discard
,也不要在swapon时加入-d
或--discard
参数。否则已被使用的空间会被重新去分配Disable zswap writeback to use the swap space only for hibernation[编辑 | 编辑源代码]
In Linux 6.8, zswap gained a per-cgroup option to disable writeback. By using systemd unit setting MemoryZSwapWriteback
(see systemd.resource-control(5) § Memory Accounting and Control) in all possible unit types, zswap writeback can be effectively disabled entirely. This allows to use zswap just like zram with the added benefit of supporting hibernation.
To avoid having to manually create twelve top level per-type drop-in files (for system and user scope
, service
, slice
, socket
, mount
, swap
units types), install zswap-disable-writebackAUR. Reboot for the settings to take effect.
Try to perform memory intensive tasks and confirm that zswap has not written anything to disk:
# cat /sys/kernel/debug/zswap/written_back_pages
0
Sleep hooks[编辑 | 编辑源代码]
Custom systemd units[编辑 | 编辑源代码]
systemd starts suspend.target
, hibernate.target
, hybrid-sleep.target
, or suspend-then-hibernate.target
for each sleep state, respectively. All the aforementioned targets pull in sleep.target
. Any of the targets can be used to invoke custom units before or after suspend/hibernate. Separate files should be created for user actions and root/system actions. Examples:
/etc/systemd/system/user-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 ExecStart=/usr/bin/sflock ExecStartPost=/usr/bin/sleep 1 [Install] WantedBy=sleep.target
/etc/systemd/system/user-resume@.service
[Unit] Description=User resume actions After=suspend.target [Service] User=%I Type=simple ExecStart=/usr/local/bin/ssh-connect.sh [Install] WantedBy=suspend.target
Enable user-suspend@user.service
and/or user-resume@user.service
for the change to take effect.
ExecStartPost=/usr/bin/sleep 1
helps prevent this.For root/system actions:
/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
/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
Combined sleep/resume unit[编辑 | 编辑源代码]
With the combined unit file, a single hook does all the work for different phases (sleep/resume) and for different targets.
Example and explanation:
/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
: After started, the service is considered active until it is explicitly stopped.StopWhenUnneeded=yes
: When active, the service will be stopped if no other active service requires it. In this specific example, it will be stopped aftersleep.target
is stopped.- Because
sleep.target
hasStopWhenUnneeded=yes
, the hook is guaranteed to start/stop properly for different tasks.
Hooks in /usr/lib/systemd/system-sleep[编辑 | 编辑源代码]
systemd-sleep runs all executables in /usr/lib/systemd/system-sleep/
, passing two arguments to each of them:
- Either
pre
orpost
, depending on whether the machine is going to sleep or waking up. suspend
,hibernate
orhybrid-sleep
, depending on which is being invoked.
The output of any custom script will be logged by systemd-suspend.service, systemd-hibernate.service or systemd-hybrid-sleep.service. You can see its output in systemd's journalctl:
# journalctl -b -u systemd-suspend.service
An example of a custom sleep script:
/usr/lib/systemd/system-sleep/example.sh
#!/bin/sh case $1/$2 in pre/*) echo "Going to $2..." ;; post/*) echo "Waking up from $2..." ;; esac
Do not forget to make your script executable.
Tips and tricks[编辑 | 编辑源代码]
Disable sleep completely[编辑 | 编辑源代码]
When using a device as e.g a server, suspending/hibernating might not be needed or it could even be undesired. Each sleep state can be disabled through systemd-sleep.conf(5):
/etc/systemd/sleep.conf.d/disable-sleep.conf
[Sleep] AllowSuspend=no AllowHibernation=no AllowHybridSleep=no AllowSuspendThenHibernate=no
英特尔快速启动技术(Intel Rapid Start Technology,IRST)[编辑 | 编辑源代码]
英特尔快速启动技术是一种休眠的固件解决方案,允许在预定义的时间间隔或电池状态后从休眠。这应该比常规休眠更快更可靠,因为它是由固件而不是在操作系统级别完成的。通常,它必须在固件中启用,固件还支持设置暂停/电池事件触发休眠后的持续时间,然而,尽管固件中支持 IRST,但某些设备仅允许通过英特尔的 Windows 驱动程序进行配置。在这种情况下,下面描述的 intel-rst 内核模块应该能够在 Linux 下配置事件。
启用英特尔快速启动技术(IRST)后,从深度睡眠中恢复需要“比从 S3 恢复长几秒,但比从休眠中恢复快得多”。
许多基于英特尔的系统都支持 IRST 固件,但需要在 SSD(而不是 HDD)上使用特殊分区。Windows 的 OEM 部署可能已经有一个预先存在的 IRST 分区,可以在 Arch Linux 安装过程中保留(而不是擦除和重新分区整个 SSD)。它应该显示为与系统 RAM 大小相等的未格式化分区。
但是,如果您打算擦除并重新分区整个驱动器(或者已经这样做了),那么如果您也计划使用该技术,则必须重新创建IRST分区。这可以通过创建一个与系统 RAM 大小相等的空分区,并将其分区类型设置为 GUID D3BFE2DE-3DAF-11DF-BA40-E3A556D89593
(对于 GPT 分区)或 ID 0x84
(对于 MBR 分区)来实现。您可能还需要在系统的固件设置中启用对IRST的支持。
IRST 休眠过程的持续时间(即将RAM的全部内容复制到特殊分区)取决于系统的 RAM 大小和 SSD 速度,因此可能需要20–60秒。一些系统可以用 LED 指示灯指示过程的完成,例如停止闪烁。
Configuring IRST hibernation events in the Linux kernel requires CONFIG_INTEL_RST
built-in or as a module. Once loaded via modprobe intel_rst
, it should create the files wakeup_events
and wakeup_time
under /sys/bus/acpi/drivers/intel_rapid_start/*/
that can be used for further configuration. This module is tersely documented, see the source drivers/platform/x86/intel/rst.c for more details.
故障排除[编辑 | 编辑源代码]
ACPI_OS_NAME[编辑 | 编辑源代码]
你也许需要调整你的 DSDT table 来让它工作。 参阅 DSDT 词条。
睡眠/休眠无法进行,或无法稳定进行[编辑 | 编辑源代码]
有相当多的错误报告指出,他们的屏幕在给出可读的错误信息前就关闭了,有时屏幕关闭了,却再也无法唤醒。这些故障在笔记本电脑和台式机上都曾发生。(这不是个官方解决方案),但切换到旧的内核,尤其是LTS内核,或许可以修复这个问题。
A problem may arise when using the hardware watchdog timer (disabled by default, see RuntimeWatchdogSec=
in systemd-system.conf(5) § OPTIONS). A buggy watchdog timer may reset the computer before the system finishes creating the hibernation image.
Sometimes the screen goes black due to device initialization from within the initramfs. Removing any modules you might have in Mkinitcpio#MODULES, removing the kms
hook and rebuilding the initramfs can possibly solve this issue, in particular with graphics drivers for early KMS. Initializing such devices before resuming can cause inconsistencies that prevents the system resuming from hibernation. This does not affect resuming from RAM. Also, check the blog article best practices to debug suspend issues.
Moving from the ATI video driver to the newer AMDGPU driver could also help to make the hibernation and awakening process successful.
For NVIDIA users, blacklisting the module nvidiafb
might help. [10]
Laptops with an Intel CPU that load the intel_lpss_pci
module for a touchpad may face kernel panic on resume (blinking caps lock) [11]. The module needs to be added to initramfs as:
/etc/mkinitcpio.conf
MODULES=(... intel_lpss_pci ...)
USB device errors[编辑 | 编辑源代码]
System may fail to suspend because of a USB device. You might see the following error:
PM: Some devices failed to suspend, or early wake event detected ... xhci_hcd 0000:02:00.0: PM: failed to suspend async: error -16
lspci may give you more information on the failing device:
$ lspci -s 02:00.0
02:00.0 USB controller: Advanced Micro Devices, Inc. [AMD] 500 Series Chipset USB 3.1 XHCI Controller
Try disconnecting devices on that port.
网络唤醒(WoL, Wake-on-LAN)[编辑 | 编辑源代码]
如果网络唤醒被启用,网卡可能会消耗电力,即使电脑处于休眠状态。
挂起后被立即唤醒[编辑 | 编辑源代码]
系统在休眠后没有断电[编辑 | 编辑源代码]
When you hibernate your system, the system should power off (after saving the state on the disk). On some firmware the S4 sleeping state does not work reliably. For example, instead of powering off, the system might reboot or stay on but unresponsive. If that happens, it might be instructive to set the HibernateMode
to shutdown
in sleep.conf.d(5):
/etc/systemd/sleep.conf.d/hibernatemode.conf
[Sleep] HibernateMode=shutdown
With the above configuration, if everything else is set up correctly, on invocation of a systemctl hibernate
the machine will shut down, saving state to disk as it does so.
休眠后启动时未找到操作系统(或启动错误的操作系统)[编辑 | 编辑源代码]
当引导磁盘是外部磁盘时,可能会发生这种情况,这似乎是由 BIOS/固件限制引起的。BIOS/固件尝试从内部磁盘启动,而休眠是从外部(或其他)磁盘上的操作系统完成的。
类似于#系统在休眠后没有断电,设置 HibernateMode=shutdown
以永久解决问题。如果您已经将自己锁定在外,您可以尝试重新启动系统4次(每次等待错误出现),这在某些BIOS上强制执行正常的引导过程。
Swap file in /home[编辑 | 编辑源代码]
If the swap file is in /home/
, systemd-logind will not be able to access it, giving the Call to Hibernate failed: No such file or directory
warning message and resulting in a need for authentication on systemctl hibernate
. This setup should be avoided, as it is considered unsupported upstream. See systemd issue 15354 for two workarounds.
PC will not wake from sleep on A520I and B550I motherboards[编辑 | 编辑源代码]
On some motherboards with A520i and B550i chipsets, the system will not completely enter the sleep state or come out of it. Symptoms include the system entering sleep and the monitor turning off while internal LEDs on the motherboard or the power LED stay on. Subsequently, the system will not come back from this state and require a hard power off. If you have similar issues with AMD, first make sure your system is fully updated and check whether the AMD microcode package is installed.
Verify the line starting with GPP0
has the enabled status:
$ cat /proc/acpi/wakeup
Device S-state Status Sysfs node GP12 S4 *enabled pci:0000:00:07.1 GP13 S4 *enabled pci:0000:00:08.1 XHC0 S4 *enabled pci:0000:0b:00.3 GP30 S4 *disabled GP31 S4 *disabled PS2K S3 *disabled GPP0 S4 *enabled pci:0000:00:01.1 GPP8 S4 *enabled pci:0000:00:03.1 PTXH S4 *enabled pci:0000:05:00.0 PT20 S4 *disabled PT24 S4 *disabled PT26 S4 *disabled PT27 S4 *disabled PT28 S4 *enabled pci:0000:06:08.0 PT29 S4 *enabled pci:0000:06:09.0
If that is enabled, you can run the following command to disable it:
# echo GPP0 > /proc/acpi/wakeup
Now test by running systemctl suspend
and let the system go to sleep. Then try to wake the system after a few seconds. If it works, you can make the workaround permanent. Create a systemd unit file:
/etc/systemd/system/toggle-gpp0-to-fix-wakeup.service
[Unit] Description="Disable GPP0 to fix suspend issue" [Service] ExecStart=/bin/sh -c "/bin/echo GPP0 > /proc/acpi/wakeup" [Install] WantedBy=multi-user.target
Do a daemon-reload and start/enable the newly created unit.
Alternatively, you can create a udev rule. Assuming GPP0
’s sysfs node is pci:0000:00:01.1
like in the example, run udevadm info -a -p /sys/bus/pci/devices/0000\:00\:01.1
to get the relevant information and create a udev rule like this one:
/etc/udev/rules.d/10-gpp0-acpi-fix.rules
KERNEL=="0000:00:01.1", SUBSYSTEM=="pci", DRIVERS=="pcieport", ATTR{vendor}=="0x1022", ATTR{device}=="0x1483", ATTR{power/wakeup}="disabled"
The udev daemon is already watching for changes in your system by default. If needed you can reload the rules manually.
Suspend from corresponding laptop Fn key not working[编辑 | 编辑源代码]
If, regardless of the setting in logind.conf, the sleep button does not work (pressing it does not even produce a message in syslog), then logind is probably not watching the keyboard device. [12] Do:
# journalctl --grep="Watching system buttons"
You might see something like this:
May 25 21:28:19 vmarch.lan systemd-logind[210]: Watching system buttons on /dev/input/event2 (Power Button) May 25 21:28:19 vmarch.lan systemd-logind[210]: Watching system buttons on /dev/input/event3 (Sleep Button) May 25 21:28:19 vmarch.lan systemd-logind[210]: Watching system buttons on /dev/input/event4 (Video Bus)
Notice no keyboard device. List keyboard devices as follows:
$ stat -c%N /dev/input/by-id/*-kbd
... /dev/input/by-id/usb-SIGMACHIP_USB_Keyboard-event-kbd -> ../event6 ...
Now obtain ATTRS{name}
for the parent keyboard device [13]. As an example, on the above list this keyboard device has event6
as device input event, it can be used to search its respective attribute name:
# udevadm info -a /dev/input/event6
... KERNEL=="event6" ... ATTRS{name}=="SIGMACHIP USB Keyboard"
Now write a custom udev rule to add the "power-switch" tag:
/etc/udev/rules.d/70-power-switch-my.rules
ACTION=="remove", GOTO="power_switch_my_end" SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="SIGMACHIP USB Keyboard", TAG+="power-switch" LABEL="power_switch_my_end"
After reloading the udev rules and restarting systemd-logind.service
, you should see Watching system buttons on /dev/input/event6
in the journal of logind.
System freezes for 60 seconds and then wakes back up or hangs after waking up[编辑 | 编辑源代码]
Since systemd v256, systemd freezes user.slice
before sleeping. This process can fail due to kernel bugs, particularly when KVM is in use.[14][15]
Messages in the logs will contain Failed to freeze unit 'user.slice'
before sleep. When such an issue occurs, trying to login (start another session) would fail with pam_systemd(process:session): Failed to create session: Job 9876 for unit 'session-6.scope' failed with 'frozen'
.
To temporarily revert back to the old behavior, edit systemd-suspend.service
, systemd-hibernate.service
, systemd-hybrid-sleep.service
, and systemd-suspend-then-hibernate.service
with the following drop-in:
[Service] Environment=SYSTEMD_SLEEP_FREEZE_USER_SESSIONS=false