内核驱动程序和内核模块有什么区别?

内核驱动程序和内核模块有什么区别?

当我lspci -k在具有 3.2.0-29-generic 内核的 Kubuntu 上执行 a 操作时,我可以看到如下内容:

01:00.0 VGA compatible controller: NVIDIA Corporation G86 [Quadro NVS 290] (rev a1)
    Subsystem: NVIDIA Corporation Device 0492
    Kernel driver in use: nvidia
    Kernel modules: nvidia_current, nouveau, nvidiafb

有内核驱动程序nvidia和内核模块nvidia_current,,nouveaunvidiafb

现在我想知道内核驱动程序和内核模块之间有什么区别?

答案1

内核模块是一些可以在运行时插入内核的编译代码,例如insmod或者modprobe

驱动程序是在内核中运行以与某些硬件设备通信的一段代码。它“驱动”硬件。计算机中的大多数硬件都有一个关联的驱动程序。 运行中的内核的很大一部分是驱动程序代码。 ²

驱动程序可以静态构建到磁盘上的内核文件中。 驱动程序也可以构建为内核模块,以便稍后可以动态加载。 (然后可能会被卸载。)

标准做法是尽可能将驱动程序构建为内核模块,而不是将它们静态链接到内核,因为这提供了更大的灵活性。然而,有充分的理由不这样做:

  • 有时,给定的驱动程序对于帮助系统启动是绝对必要的。这种情况并不像你想象的那么频繁发生,因为初始化程序特征。

  • 静态构建的驱动程序可能正是您在静态范围的系统中想要的,例如嵌入式系统。也就是说,如果您事先确切地知道始终需要哪些驱动程序并且这一点永远不会改变,那么您就有充分的理由不去打扰动态内核模块。

  • 如果静态构建内核并禁用 Linux 的动态模块加载功能,则可以防止内核代码的运行时修改。这提供了额外的安全性和稳定性,但牺牲了灵活性。

并非所有内核模块都是驱动程序。例如,Linux 内核中一个相对较新的功能是您可以加载不同的进程调度程序。另一个例子是,更复杂类型的硬件通常具有位于低级硬件驱动程序和用户空间之间的多个通用层,例如USB HID 驱动程序,它实现了USB 堆栈的特定元素,独立于底层硬件。


旁白:

  1. 这一宽泛说法的一个例外是 CPU 芯片,它没有“驱动程序”本身。您的计算机可能还包含您没有驱动程序的硬件。

  2. 操作系统内核中的其余代码提供通用服务,例如内存管理,工控机,调度等。这些服务可能主要服务于用户区应用程序,与前面链接的示例一样,或者它们可能是驱动程序或其他内核内基础设施使用的内部服务。

  3. 中的一个/boot,在启动时由引导装载程序早在启动过程

答案2

为了回答有关lspci输出的具体问题,“内核驱动程序”行指的是当前绑定到卡的驱动程序,在本例中为专有nvidia驱动程序。 “内核模块”行列出了所有驱动程序已知是可以绑定这张卡。在这里,专有驱动程序显示了不同的名称,可能是由于lspci驱动程序及其文件名的查找方式与编码到驱动程序本身的名称有关。

答案3

内核模块可能根本不是设备驱动程序

“内核驱动程序”不是一个明确定义的术语,但让我们尝试一下。

这是一个不驱动任何硬件的内核模块,因此不能合理地被视为“设备驱动程序”:

#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");

static int myinit(void)
{
    printk(KERN_INFO "hello init\n");
    return 0;
}

static void myexit(void)
{
    printk(KERN_INFO "hello exit\n");
}

module_init(myinit)
module_exit(myexit)

构建后,您可以将其用于:

insmod hello.ko

它打印hello initdmesg.

然而,有些内核模块不是设备驱动程序,但实际上很有用,例如公开内核调试/性能信息的模块。

设备驱动程序通常也是内核模块。

“设备驱动程序”的示例有点难以生成,因为它需要硬件来驱动,并且硬件描述往往很复杂。

然而,使用 QEMU 或其他模拟器,我们可以构建真实或简化硬件的软件模型,这是学习如何与硬件对话的好方法。下面是一个最小 PCI 设备驱动程序的简单示例:https://github.com/cirosantilli/linux-kernel-module-cheat/blob/6788a577c394a2fc512d8f3df0806d84dc09f355/kernel_module/pci.c

然后我们看到,在 x86 中,与硬件的对话归结为:

这些操作通常不能从用户空间完成,如下所述:用户空间和内核空间有什么区别?但也有一些例外:https://stackoverflow.com/questions/7986260/linux-interrupt-handling-in-user-space

然后,内核提供更高级别的 API,以使此类硬件交互更容易、更便携:

  • request_irq处理中断
  • ioreadX和IO内存映射
  • 适用于 PCI 和 USB 等流行协议的更高级别接口

答案4

我的答案将与吉姆一致。内核驱动程序是一个旨在驱动硬件的程序(内核模块)。 lspci 输出表明 nvidia 是内核驱动程序,因为它是loaded设备的模块。随之而来的是其他可用的内核模块。

我将补充一点,Linux 中列出和删除驱动程序的命令分别是lsmodrmmod。这表示列出模块和删除模块。

相关内容