如何卸载NVIDIA内核模块“nvidia”以安装新的驱动程序?

7

我需要升级我的nvidia驱动,因此尝试运行NVIDIA-Linux-x86_64.run文件。

然而,我看到以下消息:

ERROR: An NVIDIA kernel module 'nvidia' appears to already be loaded in your kernel.  This may be because it is in use (for example, by an X server, a CUDA program, or the NVIDIA Persistence Daemon), but this may also happen if your kernel was configured without support for module unloading.  Please be sure to exit any programs that may be using the GPU(s) before attempting to upgrade your driver.  If no GPU-based programs are running, you know that your kernel supports module unloading, and you still receive this message, then an error may have occured that has corrupted an NVIDIA kernel module's usage count, for which the simplest remedy is to reboot your computer.

我已经卸载了nvidia-drm,当我尝试卸载nvidia时。

$ sudo modprobe -r nvidia
modprobe: FATAL: Module nvidia is in use.

有人能指导我如何顺利安装这个新驱动程序吗?

谢谢。


嗨,Brandon Lee。你的问题听起来更像是一个系统管理问题而不是一个编程问题。你可能会在https://superuser.com/上或者如果这确实是一个Ubuntu特定的问题,在https://askubuntu.com上得到更多帮助。 - PaSTE
3个回答

9
使用lsof /dev/nvidia*命令查找正在使用旧驱动程序的进程。在我的情况下,是 "nvidia-persistenced"。通过pid杀死该进程,然后重试安装程序NVIDIA-***.run。
# lsof /dev/nvidia*
COMMAND    PID                USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
nvidia-pe 1334 nvidia-persistenced    2u   CHR 195,255      0t0  420 /dev/nvidiactl
nvidia-pe 1334 nvidia-persistenced    3u   CHR   195,0      0t0  421 /dev/nvidia0
nvidia-pe 1334 nvidia-persistenced    5u   CHR   195,0      0t0  421 /dev/nvidia0
nvidia-pe 1334 nvidia-persistenced    6u   CHR   195,0      0t0  421 /dev/nvidia0
nvidia-pe 1334 nvidia-persistenced    7u   CHR   195,0      0t0  421 /dev/nvidia0

0
我为此编写了Python脚本。

unload_all_nvidia_modules.py

from subprocess import run, getoutput
from shlex import split
import re

def get_all_nvidia_modules():
    all_modules = getoutput("lsmod").splitlines()
    modules_to_unload = set()
    for m in all_modules:
        m = m.strip()
        m_splitted = re.split("\s+", m)

        module_name = m_splitted[0]
        if len(m_splitted) == 4:
            deps = m_splitted[-1].split(",")
        else:
            deps = []

        if "nvidia" in module_name or any("nvidia" in d for d in deps):
            modules_to_unload.add(module_name)
            for d in deps:
                modules_to_unload.add(d)

    return modules_to_unload

def get_usage_pids(pattern):
    all_files = getoutput("lsof").splitlines()
    pids = set()
    commands = []
    for f in all_files:
        if pattern in f:
            f.strip()
            pid = re.split("\s+", f)[1]
            pids.add(pid)
            commands.append(f)

    return pids



def unload_all_nvidia_modules():
    cnt = 100
    while cnt > 0:
        cnt -= 1
        modules = get_all_nvidia_modules()

        if len(modules) == 0:
            break

        for m in modules:
            pids = get_usage_pids(m)
            for pid in pids:
                run(split(f"killall -9 {pid}"))

            run(split(f"rmmod {m}"))

if __name__ == "__main__":
    get_all_nvidia_modules()
    unload_all_nvidia_modules()


使用方法:
sudo python3 unload_all_nvidia_modules.py

警告:

请自行承担使用此脚本的风险。保存您的工作和所有打开的文档,因为此脚本将“终止”所有使用NVIDIA驱动程序的进程(例如GUI程序)。


在不给用户机会进行审查和确认的情况下,随意终止一系列进程是导致工作丢失的一个原因,尤其是其中一个进程是用户的X会话或任何等效的进程。同样,在发送SIGKILL信号之前,应该先发送SIGTERM信号,并等待几秒钟(例如,systemd默认的90秒),然后再发送SIGKILL信号给那些无法正常关闭的进程。立即发送SIGKILL信号会增加那些对数据不够谨慎的应用程序丢失工作或数据损坏的风险。 - Simon Ruggier
@SimonRuggier 谢谢你的评论。我知道你写的是什么。我只是为了自己的使用情况而创建了这个脚本,并在这里分享,以防有人觉得有用。我在无头机器上使用它,所以没有X进程。如果你想在发送SIGTEM之前等待一下,那就去做吧。 - RedEyed

0

我刚刚删除了现有的驱动程序并重新安装了它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接