1. 程式人生 > 實用技巧 >Ubuntu/Liinux睡眠無法喚醒解決方法:ACPI設定

Ubuntu/Liinux睡眠無法喚醒解決方法:ACPI設定

最近給筆記本換了一個固態,順便就重灌了一下系統,版本是Ubuntu 20.10。裝完之後各種功能基本都是正常的,觸控板輕觸單擊、雙指右鍵等功能開箱即用。但是在安裝完最新的Nvidia驅動之後就出現了問題,系統掛起之後就無法喚醒了,只有一個游標在螢幕上一直閃。

這種基本上都是硬體的相容問題,要麼就寄希望於核心和驅動的更新,要麼就換一個linux發行版。但是由於我重灌之前應該是正常的,就導致我非常難受,想要解決這個問題。linux這類問題千變萬化,很多時候搜遍網際網路也沒法解決。但這次運氣不錯,找到了問題的癥結,並且有一定的普適性。

I found a solution which should work for everyone.

Worked for me! In fact, it is the only damned thing that ever worked for me.

問題原因

Linux系統向上為使用者提供良好的操作介面,向下管理各種硬體和資源。其中包括開關機、掛起和喚醒、休眠等,還有Fn功能鍵等。軟體與硬體溝通中間渠道就是通過韌體,這部分是由硬體廠商提供的,一般寫在BIOS裡。ACPI是一個重要的規範,稱作高階配置與電源介面。由於現在Windows是作業系統的絕對的主流,很多廠商在設計的時候就沒有考慮到其他作業系統比如Linux,就會導致很多功能無法正常的工作。

不過好在這個現象已經引起Linux開發者的注意,並且提供了一個acpi_osi=

的選項,可以讓韌體提供和Windows相同的功能。

解決方法

ACPI的DSDT提供了對作業系統的識別功能,我們可以用如下的命令檢視DSDT支援什麼樣的系統版本:

$ sudo strings /sys/firmware/acpi/tables/DSDT | grep -i 'windows ' | sort

在我的電腦上包括Windows 2009Windows 2012Windows 2013三個返回值,分別代表的是Windows 7,8和8.1。接下來只需要給核心增加一個引數,就可以讓硬體識別為Windows了。具體的方法是在/etc/defalut/grub中給GRUB_CMDLINE_LINUX增加acpi_osi=

引數,大概像下面這個樣子:

GRUB_CMDLINE_LINUX="acpi_osi=! \"acpi_osi=Windows 2015\""

接著,執行sudo update-grub命令就可以將配置部署到Grub上了。重啟系統,執行

$ cat /proc/cmdline

可以看到啟動引數已經被新增成功了。在這種情況下,如果問題是這個導致的話已經可以解決了。如果不行,幾個Windows版本都可以試一試,我用的是Windows 2009才可以。但即使你的問題沒有被完全解決,仍然推薦保留這個選項來保證ACPI的全功能,包括省電、CPU保護等不明顯的功能。

自動化指令碼

如果不想了解那麼多細節的話,可以直接通過一個指令碼自動化的完成上述的修改。

#!/bin/sh
VERSION="$(sudo strings /sys/firmware/acpi/tables/DSDT | grep -i 'windows ' | sort | tail -1)"
echo 'Linux kernel command-line options required: acpi_osi=! "acpi_osi='$VERSION'"'
read -p "Do you want to add this setting (y/n) ? " answer
if [ x$answer != xY -a x$answer != xy ]; then
  exit 1
fi
echo "Existing Command Line: ` sed -n '/.*linux[[:space:]].*root=\(.*\)/{s//BOOT_IMAGE=\1/ p;q;}' /boot/grub/grub.cfg `"
if grep -m 1 'acpi_osi=Windows' -q /etc/default/grub; then
  echo "There is already an entry; please remove it from /etc/default/grub and redo 'sudo update-grub' then re-run this script"
  exit 2
fi
sudo sed -i "s/^\(GRUB_CMDLINE_LINUX=.*\)\"$/\1 acpi_osi=! \\\\\"acpi_osi=$VERSION\\\\\"\"/" /etc/default/grub
echo "Modified Command Line: ` sed -n '/.*linux[[:space:]].*root=\(.*\)/{s//BOOT_IMAGE=\1/ p;q;}' /boot/grub/grub.cfg `"
sudo update-grub

儲存為.sh檔案執行即可。

終於可以愉快的休眠了,這個功能對筆記本來說太重要了。

  1. https://forums.developer.nvidia.com/t/solution-for-nvidia-sleep-wake-issue-in-linux/110911
  2. https://iam.tj/prototype/enhancements/Windows-acpi_osi.html