![升级到 4.4.0-116 内核后登录循环:图形登录屏幕 -> 黑屏 -> 图形登录屏幕](https://linux22.com/image/1204163/%E5%8D%87%E7%BA%A7%E5%88%B0%204.4.0-116%20%E5%86%85%E6%A0%B8%E5%90%8E%E7%99%BB%E5%BD%95%E5%BE%AA%E7%8E%AF%EF%BC%9A%E5%9B%BE%E5%BD%A2%E7%99%BB%E5%BD%95%E5%B1%8F%E5%B9%95%20-%3E%20%E9%BB%91%E5%B1%8F%20-%3E%20%E5%9B%BE%E5%BD%A2%E7%99%BB%E5%BD%95%E5%B1%8F%E5%B9%95.png)
无法登录桌面环境apt upgrade && reboot
:输入密码后屏幕闪烁变为黑屏并返回登录屏幕。通过终端 ( Ctrl+Alt+F1) 登录可以正常工作。
/var/log/Xorg.0.log
说:
(EE) NVIDIA:无法初始化 NVIDIA 内核模块。请参阅
(EE) NVIDIA:系统内核日志以了解更多错误消息,以及
(EE) NVIDIA:查阅 NVIDIA README 以了解详细信息。
(EE) 未检测到任何设备。
$ dmesg
说:
nvidia:版本魔法'4.4.0-116-generic SMP mod_unload modversions'应该是'4.4.0-116-generic SMP mod_unload modversions retpoline'
尝试手动加载 nvidia 驱动程序失败:
$ sudo modprobe nvidia
modprobe: ERROR: could not insert 'nvidia': Exec format error
答案1
问题在于 gcc 版本不支持 retpoline (什么是 retpoline 以及它是如何工作的?). 查看Ubuntu Bug:2 月 21 日的 4.4.0-116 内核更新破坏了 Nvidia 驱动程序(14.04 和 16.04)。
就我而言,清除ppa:ubuntu-toolchain-r/test
安装默认 gcc 版本并使用 DKMS 重建 nvidia 模块(通过重新安装 4.4.0-116 内核)可以解决问题。请参阅@cjjefcoat 在错误跟踪器上发布的说明。
ppa:ubuntu-toolchain-r/test
通过清除版本恢复默认 gcc :
$ sudo apt-get install ppa-purge
$ sudo ppa-purge ppa:ubuntu-toolchain-r/test
gcc 版本(在 Ubuntu 16.04 上)具有 retpoline 支持:
$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
重新安装内核:
$ sudo apt-get purge linux-headers-4.4.0-116 linux-headers-4.4.0-116-generic linux-image-4.4.0-116-generic linux-image-extra-4.4.0-116-generic linux-signed-image-4.4.0-116-generic
$ sudo apt-get install linux-generic linux-signed-generic
检查 nvidia 模块:
$ modinfo nvidia_xxx -k 4.4.0-116-generic | grep vermagic
vermagic: 4.4.0-116-generic SMP mod_unload modversions retpoline
用你的版本替换_xxx
--只需在之后按TAB即可modinfo nvidia
retpoline
应该在输出中。
之后reboot
成功完成。
如果您已经有兼容的 gcc 版本,则可以使用dkms
命令重建 nvidia 模块,而无需重新安装内核:
# dkms remove nvidia-xxx/yyy.zzz -k 4.4.0-116-generic
# dkms install nvidia-xxx/yyy.zzz -k 4.4.0-116-generic
我决定重新安装内核,以更新使用错误的 gcc 版本通过 DKMS 重新构建的所有模块。
答案2
我不知道 Ask Ubuntu 是否是解决这些问题的正确地方,但是——正如我需要新的g++
并且仍定期更新内核 — — 我编写了一个 bash 脚本,用于 (1) 清除ppa:ubuntu-toolchain-r/test
、(2) 为选定的内核重建所有 DKMS 模块、(3) 安装g++-7
回 — —这个答案。
该脚本按“原样”提供,不提供任何形式的担保。
除非您理解每一行的含义,否则请不要使用它。
它的目的是节省您手动完成的事情的时间(而不是做您不理解的“魔术”)。
剧本:
#!/bin/bash -e
for list in /etc/apt/sources.list.d/ubuntu-toolchain-r*.list; do
sudo cp -a "$list" "$list.backup"
echo "Backed up $list to $list.backup"
done
sudo ppa-purge ppa:ubuntu-toolchain-r/test
readarray -t kernels < <(ls -1 /lib/modules)
echo "Kernels: ${kernels[*]}"
for kernel in "${kernels[@]}"; do
dkms_modules=($(sudo dkms status -k "$kernel" | sed -r 's#^([^,]+), ([^,]+), .*$#\1/\2#'))
while true; do
echo
read -p "Reinstall DKMS-modules (${dkms_modules[*]}) on kernel $kernel? [Y/n] " choice
if [ "${choice^^}" = N ]; then continue 2; fi
if [ "${choice^^}" = Y ] || [ -z "$choice" ]; then break; fi
echo "Expected 'y', 'n' or '', but got '$choice'"
done
echo
for dkms_module in "${dkms_modules[@]}"; do
sudo dkms remove -k "$kernel" "$dkms_module"
sudo dkms install -k "$kernel" "$dkms_module"
done
echo
for module in /lib/modules/"$kernel"/updates/dkms/*.ko; do
vermagic="$(modinfo -F vermagic $module)"
echo -n "Vermagic for $(basename ${module%.ko}): $vermagic -- "
fgrep -q retpoline <<<"$vermagic" && echo ok || echo "'retpoline' is missing!!!"
done
done
for list in /etc/apt/sources.list.d/ubuntu-toolchain-r*.list; do
sudo mv "$list.backup" "$list"
echo "Restored $list from $list.backup"
done
sudo apt update
sudo apt install g++-7
sudo apt dist-upgrade