我在这里特别想知道的是:无论底层硬件如何,Linux 内核如何在所有不同的 PC 上工作。
或者一般来说,任何内核(微软的 NT 内核、mac os 和 Linux)如何在任何 PC 上工作,无论 PC 的硬件配置如何。
这里用一个场景来解释我的疑问:与PC-2相比,PC-1的蓝牙、键盘、wifi等配置不同,并且由不同的制造商开发。为了使所有这些硬件正常工作,我想内核应该具有特定于硬件的代码来启用这些硬件。我相信内核有设备驱动程序层,它应该在哪里启用这些硬件?或者它只是从其他地方加载设备特定的固件?硬件特定代码到底位于内核中的哪里?另外,在消除疑问的同时,我遇到了 HAL、BSP。这些是什么以及这些层在内核中的位置?
答案1
我在这里特别想知道的是,无论底层硬件如何,Linux 内核如何在所有不同的电脑上工作
首先,只要内核是针对特定架构编译的,它就可以在任何 PC 上运行。对于通用计算机,架构往往是相同的 (x86_64/amd64),但当您处理嵌入式设备时,这种情况会发生变化。
设备树
除了编译之外,内核本身与硬件无关。我给你设备树!
Linux 内核处理不可发现硬件的方式是通过设备树。这告诉内核有关 CPU、内存、总线、通过 I2C、SPI 连接的设备等信息。设备布局不是硬编码的,而是可以通过设备树进行更改。当你理解它时,这一切真的很神奇。设备树还通过参数告诉内核应该为特定设备使用哪个驱动程序compatible
。
设备树可以以各种不同的方式存储,具体取决于内核的编译方式,但通常可以在/proc/device-tree
或下看到层次结构/sys/firmware/devicetree/base
。
对于 USB 设备之类的东西,这一切都由 USB 驱动程序处理。内核有用于控制键盘和鼠标等东西的基本代码。一些供应商有自定义驱动程序,然后随设备一起提供。
模块
对于驱动程序,Linux 内核使用称为内核模块。所有模块都可以在 下找到/lib/modules
。有两种类型的模块:可加载模块和内置模块。您可以使用该命令查看所有加载的模块lsmod
。当内核在设备树中找到某个设备时,或者甚至当您将设备插入外设时,它会查看是否有可以为该设备加载的模块,并且该模块将成为该设备的驱动程序。
可加载模块的好处是它可以使内核映像保持更小。这些模块可以单独编译。内置模块被编译到内核中,从而增加了实际图像大小。您还可以在内核运行时编译模块并将其加载到内核中,但这是一个完全不同的主题。
巴西石油公司
当供应商为其自己的硬件(包括处理器和连接的硬件)提供内核和一堆特定模块时,您就进入了 BSP(板支持包)。有时供应商会对现有模块进行更改或随内核提供自定义模块。一些供应商对内核本身进行了更改,整个自定义包成为 BSP。这种情况在嵌入式世界中经常发生。
哈尔
HAL(硬件抽象层)可以与 BSP 同义。我还没有看到它在 Linux 世界中得到如此多的使用,但是当你进入微控制器时,它的使用非常频繁。本质上,HAL 是一组用于访问硬件的库,使与硬件的接口变得更加容易。例如,使用 WiFi 芯片,它会为您提供连接到 AP、扫描网络、创建接入点等的基本例程,从这个意义上讲,它有点像驱动程序。