一、阅读工具
ctags -R
在终端中执行 ctags -R
命令时,系统提示找不到 ctags
命令。这是因为您的系统中未安装 ctags
工具。
1. 选择安装方式
可以选择以下几种方式来安装 ctags
:
-
通过 APT 安装 Exuberant Ctags
sudo apt install exuberant-ctags
- 这是一个比较老的版本,但在许多系统中都能正常工作。
-
通过 APT 安装 Universal Ctags
sudo apt install universal-ctags
- 这是一个更新版本,功能更强大,推荐使用。
- 通过 Snap 安装 Universal Ctags
sudo snap install universal-ctags
- 如果您的系统支持 Snap,可以通过 Snap 安装最新版本。
2. 安装命令示例
假设您选择安装 universal-ctags
,可以使用以下命令:
sudo apt update # 更新包列表
sudo apt install universal-ctags # 安装 universal-ctags
3. 确认安装成功
安装完成后,您可以通过以下命令确认 ctags
是否已正确安装:
ctags --version
如果成功,您将看到 ctags
的版本信息。
4. 重新运行 ctags
安装完成后,您可以再次运行您的原始命令:
ctags -R
这将递归地为当前目录下的所有源代码文件生成标签文件 tags
,以便于在代码编辑器中进行导航。
查看索引文件
ls -l tags
5. 使用说明
ctags
工具可以帮助开发者生成可以在编辑器中跳转的标签,对于大型项目特别有用,可以提高代码浏览的效率。可以在生成的 tags
文件中查找变量、函数等定义并快速跳转。
vi net/ipv4/af_inet.c
可以快速查找到变量位置
您提到的快捷键主要是在使用支持 ctags
的文本编辑器(如 Vim)时,用于快速导航到函数或变量的定义。这些快捷键可以帮助开发者在代码中快速查找和跳转,提升开发效率。以下是对这些快捷键的详细解释:
(1) Ctrl + ]
- 作用:在 Vim 中使用
Ctrl + ]
来跳转到光标下的标识符(例如函数名或变量名)的定义位置。这是基于ctags
生成的标签文件(通常是tags
文件)进行的跳转。 - 使用方法:
- 将光标放在您想要跳转的函数或变量名上。
- 按下
Ctrl + ]
,Vim 会查找标签文件并跳转到该标识符的定义。
(2) Ctrl + g
- 作用:在 Vim 中使用
Ctrl + g
可以显示光标所在位置的文件名和行号信息。此命令有助于您在跳转时了解当前光标的位置。 - 使用方法:
- 在任何时候按下
Ctrl + g
,您将看到状态栏显示当前文件的信息。
- 在任何时候按下
在 Vim 编辑器中,您提到的 g Ctrl + ]
是一个用于跳转到标签定义的命令。这个命令的使用和 Ctrl + ]
类似,但 g
的前缀提供了一些额外的功能或上下文。以下是关于 g Ctrl + ]
的详细解释:
(3)g Ctrl + ]
的功能
- 作用:在 Vim 中,
g Ctrl + ]
用于跳转到光标下的标识符的定义,类似于Ctrl + ]
,但通常用于更复杂的情境,比如在使用多重标签文件或其他复杂环境时。 - 使用场景:
- 当有多个标签文件时,
g Ctrl + ]
可以帮助您更精确地查找对应的标签定义。 - 如果您使用了多个标签源(例如,多个语言或多个库),这个命令可以在这些标签之间进行更智能的跳转。
- 当有多个标签文件时,
将光标放在要跳转的函数或变量名上:确保光标位于您想要查看其定义的标识符上。
按 g Ctrl + ]
:执行该命令后,Vim 将查找并跳转到该标识符的定义位置。
- 标签文件:为了使这些跳转命令有效,您需要在项目目录中生成一个标签文件(通常是
tags
文件),这可以通过ctags
工具实现。 - 返回跳转:要返回到先前的位置,您可以使用
Ctrl + t
或Ctrl + o
(返回到上一个光标位置)。
(4)Ctrl + o
- 作用:在 Vim 中使用
Ctrl + o
可以返回到您之前的位置。这对于在代码中频繁跳转时特别有用,可以帮助您快速返回到跳转之前的位置。 - 使用方法:
- 在跳转到某个定义后,如果您需要返回,按下
Ctrl +o
即可返回到之前的位置。
- 在跳转到某个定义后,如果您需要返回,按下
这些快捷键的组合提供了一种高效的方式来浏览和理解代码,尤其是在大型项目中。通过使用 ctags
和这些导航快捷键,您可以快速定位函数和变量的定义,从而提高开发效率。
(5)其他相关快捷键
以下是一些其他有用的快捷键:
- Ctrl + t:返回上一次跳转的位置。这是与
Ctrl + ]
配对使用的,如果您跳转到了某个定义,可以用Ctrl + t
返回。 - :tags:查看当前项目的标签列表。
- :tag :跳转到指定的标签(例如函数名)。
通过熟练使用这些快捷键,您可以在代码中高效地进行导航和查找。
二、源码功能详解
2.1 linux-5.10.99源码目录介绍
1. arch/
包含针对不同硬件架构(如 x86、ARM、MIPS 等)的代码。每种架构都有自己的子目录尽可能支持各种极为复杂的硬件特点。
2. block/
包含与块设备相关的代码和驱动程序。这些代码负责处理例如硬盘和 SSD 等传统的块存储设备的输入和输出。
3. certs/
存储内核使用的证书文件,尤其是和模块签名相关的证书,确保模块从可信源加载。
4. COPYING
内核源码的复制协议(如 GPL 许可证)文件,阐明这一开源代码的使用和分发条件。
5. CREDITS
该文件列出为 Linux 内核发展做出贡献的开发者及其贡献。对重要项目和开发者有一个基本的记录。
6. Documentation/
提供有关内核的各个方面的文档,包括 API 使用,功能实现和设计理念等,帮助开发者更好地理解和使用内核。
7. drivers/
包含整个内核的设备驱动程序,这些驱动允许内核与外围设备进行互动,包括 USB、PCI 等。
8. fs/
文件系统代码,支持哪些文件系统(例如 ext4、XFS 等),并提供文件和目录的管理功能。让我们以人类能够理解文件或者目录的方式去访问存储设备。
9. include/
包含内核需要的头文件,其中定义了一些接口、结构体及内核所需的共享功能。
10. init/
包含用于内核启动和初始化功能的代码。在系统启动时,由这些代码完成内核的初始化工作。
11. Kbuild
用于编译内核模块的构建文件,定义了如何为构建过程中的不同模块和功能处理源代码。
12. Kconfig
用于配置内核构建选项的文件,以管理可配置性选项的设置,通常通过 make menuconfig
可以进行图形化选择。是属于编译系统的一部分。用于内核的编译配置。
13. LICENSES
包含各种许可证文本的文件,用于解释和说明使用和遵循的许可证类型。
14. lib/
内核内部用于共享函数的库代码,提供数据结构和算法支持,简化内核开发的复杂性。
15. Makefile
构建和编译内核的主要规则文件,具体说明了怎样进行内核的构建。
16. MAINTAINERS
列出各个部分的维护人员和联系方式,以指明每部分代码的负责开发者。
17. mm/
与内存管理相关的代码,包括物理和虚拟内存处理内核需要进行的细节。
18. modules.builtin
列表,显示所有在内核构建中内置的模块,通常是在启动表中。
19. modules.builtin.modinfo
提供内置模块的信息,类似于模块的头信息。
20. modules.order
显示模块的编译顺序,这样可以为模块依赖关系设置顺序。
21. modules-only.symvers
包含模块符号的版本,通常记录参与模块依赖和连接规范所需的信息。
22. net/
网络功能的实现,包括所谓的各种网络协议(如 TCP/IP 等)。
23. README
在源代码根目录下的文件,提供一般性的介绍、开发指南和联系信息。
24. security/
管理系统的安全性及防护机制,包括 SELinux 等重要安全增强特性。
25. samples/
提供设备驱动和内核功能的示例代码,能帮助开发者理解实现方式与使用。
26. scripts/
包含用于自动化内核构建和测试任务,以及其他有用工具的脚本。
27. sound/
音频驱动和相关功能的实现,管理声卡和其他音频设备。
28. System.map
列出内核符号与地址的映射,通常用于调试信息中有助于解析错误信息。
29. tools/
工具和程序集,提供对内核的监控、分析、调试帮助。
30. usr/
用户空间相关功能的实现,此部分代码为用户空间与内核空间的交互提供支持。
31. vmlinux
最终生成的内核可执行镜像。该文件包含内核所有必须运行的代码。
32. vmlinux.o
中间目标文件,最终会合并生成 vmlinux
,为内核尝试调试或其他操作性调整提供支持。
33. vmlinux.symvers
记录内核和模块的符号版本,主要用途是在模块构建时确定哪些符号是兼容的。
34. ipc\
进程相关的代码,内核通讯的机制。
34. kernel
Linux 内核是操作系统的核心部分,负责管理系统资源,提供硬件抽象层,并支持各种系统调用。
Linux 内核的架构通常是单内核(Monolithic Kernel),这意味着所有功能模块(如设备驱动、文件系统、网络协议等)在同一个内核空间内运行。但它也支持可加载模块(Loadable Kernel Modules, LKM),允许在运行时动态加载、卸载驱动和功能模块,提高了灵活性和扩展性。
Linux 内核是开源的,使用GPL 许可证,开发者来自世界各地,形成了一个强大的社区支持。内核以定期发布的版本活动,主要的发布版本号遵循 “主版本.次版本.修订版本” 的格式。例如,Linux 5.10 是第五个主版本,第四个次版本,零个修订版本。
通过配置文件(如 Kconfig)和 Makefile,开发者可以根据需求选择内核卷入内容,还可以添加或去掉某些模块。在开发过程中,内核必须经过编译过程以生成与硬件相匹配的可执行内核映像。
内核通过系统调用与用户空间交互,提供高层 API供应用程序使用。这为应用程序提供了对底层硬件及资源的管理。
在 Linux 内核源代码中,不同的目录用于组织和管理特定的内核代码和功能。对于 linux-5.10.99/arch/arm/kernel
与 linux-5.10.99/kernel
这两个目录,主要的区别在于它们所包含的代码和涵盖的功能。以下是对这两个目录的详细说明:
arch/arm/kernel
- 架构特定的代码:
arch/arm/kernel
目录包含与 ARM 架构相关的内核代码。它提供了与 ARM 处理器架构紧密相关的实现细节。 - 硬件抽象:此目录下的代码处理ARM架构的特定功能,包括中断控制、上下文切换、系统调用等底层操作。
- 启动代码:包含系统引导时执行的代码,比如初始化 CPU、设置内存等。
- 平台相关功能:与具体硬件平台或开发板有关的定义和实现,也可能涉及设备驱动的代码,特定于其在 ARM 架构的表现。
kernel
- 通用内核功能:
kernel
目录包含跨架构的内核功能,它不是特定于某一架构(如 ARM、x86 等)的。例如,这里有与进程管理、内存管理、调度、信号处理、键盘管理等通用处理逻辑相关的内容。 - 更高层的抽象:提供的是对内核核心功能的通用实现,与实现具体硬件或架构所需的细节直接分离,以提高可维护性和可移植性。
- 系统调用接口:定义和实现系统调用的机制,并处理用户空间与内核空间的交互。
区别总结
arch/arm/kernel
:专注于 ARM 架构的特定实现和操作,包括启动和与硬件打交道的细节。kernel
:关注内核的核心功能,实现与具体架构无关的通用特性。
以上这些文件和目录共同构成了 Linux 内核的主要框架,各自的功能和作用相辅相成,共同定义了内核的实现和能力。
2.2 linux-5.10.99/arch/arm目录介绍
Linux 内核源代码目录和文件的详细介绍,主要集中在以 mach-
前缀为名的架构特定子目录:
1. boot/
此目录包含内核引导相关的代码,负责设置初始环境为操作系统运行准备,以及初始化系统所需的各个元素。
2. built-in.a
内核构建过程中的一个库文件,包含所有通过内核配置选项编译进内核的对象文件。
3. common/
包含一些通用代码,通常是各个特定架构可共享的代码段,减少冗余和提高可重复使用性。
4. configs/
该目录中包含不同配置选项的文件,指导如何编译特定的内核版本。
5. crypto/
欲为内核提供的加密与解密库和接口,支持各种加密算法,并保证数据的安全性。
6. include/
头文件目录,包含声明过去接口和所需结构的通用头文件,帮助代码无论而不至于冗杂。
7. kernel/
核心的内核代码,包括调度、进程管理等功能实现,确保系统正常高效地运作。
8. Kbuild
定义内核构建系统所需的规则, dictating how the files in this directory are built.
9. Kconfig
用于描述构建内核时可供选择的配置选项,用户可通过配置界面进行选择。
10. Kconfig.assembler
特定于汇编文件类型的 Kconfig,列出了指需要的配置选项,确保所需汇编可以正确编译。
11. Kconfig.debug
包含调试相关的配置选项,供修改和维护内核以便进行错误诊断和修复。
12. lib/
包含与常用功能和库相关的代码和实现。
13. Makefile
主生成文件,用以定义如何组装和编译内核的具体规则。
14. mm/
内存管理的代码,处理内存分配、虚拟内存和缓存管理。
15. modules.order
此文件定义了模块的顺序,指定各模块编译时的加载顺序或所需抵赖关系。
16. net/
提供网络协议栈和网络设备相关功能的实现,包括对 TCP/IP 等协议的支持。
17. tools/
一些辅助工具的实现,便于开发和测试内核及其功能。
18. 以 mach-
前缀开头的目录:
这些目录因特定于不同的硬件架构而成功设置,它们包含功能模块和目标,要支持的每个特定架构 Responsible for making Linux run on a specific architecture:
- mach-alpine: 与 Alpine 架构相关的代码和配置。
- mach-artpec: 为 Artpec 架构提供的配置和实现。
- mach-actions: 包含操作系统在 Actions 处理器上的实现。
- mach-at91: 针对 Atmel AT91 系列处理器的代码,提供支持。
- mach-davinci: 为 Davinci 系列处理器提供特定实现。
- mach-efm32, mach-mvebu, mach-tegra, etc.: 各自对应其他平台和系统。
这些 mach-
目录统一组织在内核中,每个子文件夹内相关于之平台的驱动,外设管理和内核初始化逻辑,以达到功能兼容。
19. 其他特定的子目录:
- plat-omw: 提供像 OMAP 等的具体硬件平台的实现。
- xen: 与 Xen 虚拟化框架相关的代码。
每个特定 mach-
或 plat-
子目录及相关配置路径在实现专用平台的支持方面至关重要,提升功能性实现和设备兼容,使得内核在多样硬件上运作。
三、drivers⽂件夹中Makefile、Kconfig⽂件的含义
find ./ name Makfile
目录底下有多个Makefile
3.1 Makefile
1. 源码+注释
# SPDX-License-Identifier: GPL-2.0
# 指明该文件遵循 GPL-2.0 许可证。
# Makefile for the Linux kernel device drivers.
# 该文件是针对 Linux 内核设备驱动程序的 Makefile。
# 15 Sep 2000, Christoph Hellwig <hch@infradead.org>
# 该 Makefile 的原作者和日期。
# Rewritten to use lists instead of if-statements.
# 使用列表而不是 if 语句进行重写的说明。
# 向 obj-y 添加 irqchip 目录中的对象文件
obj-y += irqchip/
# 向 obj-y 添加 bus 目录中的对象文件
obj-y += bus/
# 如果 CONFIG_GENERIC_PHY 被启用,则添加 phy 目录
obj-$(CONFIG_GENERIC_PHY) += phy/
# GPIO 必须在配置的 pinctrl 之后,因为 GPIO 可能需要多路复用引脚等
obj-$(CONFIG_PINCTRL) += pinctrl/
# 如果 CONFIG_GPIOLIB 被启用,则添加 gpio 目录
obj-$(CONFIG_GPIOLIB) += gpio/
# 向 obj-y 添加 pwm 目录中的对象文件
obj-y += pwm/
# 向 obj-y 添加 pci 目录中的对象文件
obj-y += pci/
# 如果配置为 PARISC,则添加 parisc 目录
obj-$(CONFIG_PARISC) += parisc/
# 如果配置为 RAPIDIO,则添加 rapidio 目录
obj-$(CONFIG_RAPIDIO) += rapidio/
# 向 obj-y 添加 video 目录中的对象文件
obj-y += video/
# 向 obj-y 添加 idle 目录中的对象文件
obj-y += idle/
# IPMI 必须在 ACPI 之前,以提供 IPMI opregion 支持
obj-y += char/ipmi/
# 如果启用了 ACPI,则添加 acpi 目录
obj-$(CONFIG_ACPI) += acpi/
# 如果启用了 SFI,则添加 sfi 目录
obj-$(CONFIG_SFI) += sfi/
# PnP 必须在 ACPI 之后,因为它最终需要检查 ACPI 是否已被使用
obj-$(CONFIG_PNP) += pnp/
# 向 obj-y 添加 amba 目录中的对象文件
obj-y += amba/
# 向 obj-y 添加 clk 目录中的对象文件
obj-y += clk/
# 许多驱动程序将需要 DMA,因此必须尽早可用
obj-$(CONFIG_DMADEVICES) += dma/
# SOC 特定基础设施驱动程序
obj-y += soc/
# 如果配置为 VIRTIO,则添加 virtio 目录
obj-$(CONFIG_VIRTIO) += virtio/
# 如果配置为 VDPA,则添加 vdpa 目录
obj-$(CONFIG_VDPA) += vdpa/
# 如果配置为 XEN,则添加 xen 目录
obj-$(CONFIG_XEN) += xen/
# 调节器要放在很早的位置,因为某些子系统依赖于它们进行初始化
obj-$(CONFIG_REGULATOR) += regulator/
# 重置控制器要放在很早的位置,因为 GPU 驱动程序可能依赖于它们进行初始化
obj-$(CONFIG_RESET_CONTROLLER) += reset/
# tty/ 必须放在 char/ 之前,以便 VT 控制台成为启动时的默认值
obj-y += tty/
# 向 obj-y 添加 char 子目录中的对象文件
obj-y += char/
# iommu/ 必须在 GPU 之前,因为 GPU 使用 IOMMU 控制器
obj-y += iommu/
# GPU 目录在 char 之后,因为 AGP 与 DRM 启动有关,并在 iommu 之后
obj-y += gpu/
# 如果启用了 Connector,则添加 connector 目录
obj-$(CONFIG_CONNECTOR) += connector/
# i810fb 和 intelfb 依赖于 char/agp/
# 如果配置为 FB_I810,则添加 video/fbdev/i810 目录
obj-$(CONFIG_FB_I810) += video/fbdev/i810/
# 如果配置为 FB_INTEL,则添加 video/fbdev/intelfb 目录
obj-$(CONFIG_FB_INTEL) += video/fbdev/intelfb/
# 如果配置为 PARPORT,则添加 parport 目录
obj-$(CONFIG_PARPORT) += parport/
# 如果配置为 NVM,则添加 lightnvm 目录
obj-$(CONFIG_NVM) += lightnvm/
# 向 obj-y 添加 base、block、misc、mfd、nfc 目录中的对象文件
obj-y += base/ block/ misc/ mfd/ nfc/
# 如果配置为 LIBNVDIMM,则添加 nvdimm 目录
obj-$(CONFIG_LIBNVDIMM) += nvdimm/
# 如果配置为 DAX,则添加 dax 目录
obj-$(CONFIG_DAX) += dax/
# 如果配置为 DMA_SHARED_BUFFER,则添加 dma-buf 目录
obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf/
# 如果配置为 NUBUS,则添加 nubus 目录
obj-$(CONFIG_NUBUS) += nubus/
# 向 obj-y 添加 macintosh 目录中的对象文件
obj-y += macintosh/
# 如果配置为 IDE,则添加 ide 目录
obj-$(CONFIG_IDE) += ide/
# 向 obj-y 添加 scsi 目录中的对象文件
obj-y += scsi/
# 向 obj-y 添加 nvme 目录中的对象文件
obj-y += nvme/
# 如果配置为 ATA,则添加 ata 目录
obj-$(CONFIG_ATA) += ata/
# 如果配置为 TARGET_CORE,则添加 target 目录
obj-$(CONFIG_TARGET_CORE) += target/
# 如果配置为 MTD,则添加 mtd 目录
obj-$(CONFIG_MTD) += mtd/
# 如果配置为 SPI,则添加 spi 目录
obj-$(CONFIG_SPI) += spi/
# 如果配置为 SPMI,则添加 spmi 目录
obj-$(CONFIG_SPMI) += spmi/
# 如果配置为 HSI,则添加 hsi 目录
obj-$(CONFIG_HSI) += hsi/
# 如果配置为 SLIMBUS,则添加 slimbus 目录
obj-$(CONFIG_SLIMBUS) += slimbus/
# 向 obj-y 添加 net 目录中的对象文件
obj-y += net/
# 如果配置为 ATM,则添加 atm 目录
obj-$(CONFIG_ATM) += atm/
# 如果配置为 FUSION,则添加 message 目录
obj-$(CONFIG_FUSION) += message/
# 向 obj-y 添加 firewire 目录中的对象文件
obj-y += firewire/
# 如果配置为 UIO,则添加 uio 目录
obj-$(CONFIG_UIO) += uio/
# 如果配置为 VFIO,则添加 vfio 目录
obj-$(CONFIG_VFIO) += vfio/
# 向 obj-y 添加 cdrom 目录中的对象文件
obj-y += cdrom/
# 向 obj-y 添加 auxdisplay 目录中的对象文件
obj-y += auxdisplay/
# 如果配置为 PCCARD,则添加 pcmcia 目录
obj-$(CONFIG_PCCARD) += pcmcia/
# 如果配置为 DIO,则添加 dio 目录
obj-$(CONFIG_DIO) += dio/
# 如果配置为 SBUS,则添加 sbus 目录
obj-$(CONFIG_SBUS) += sbus/
# 如果配置为 ZORRO,则添加 zorro 目录
obj-$(CONFIG_ZORRO) += zorro/
# 如果配置为 ATA_OVER_ETH,则添加 block/aoe 目录
obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/
# 如果配置为 PARIDE,则添加 block/paride 目录
obj-$(CONFIG_PARIDE) += block/paride/
# 如果配置为 TC,则添加 tc 目录
obj-$(CONFIG_TC) += tc/
# 如果配置为 USB_PHY,则添加 usb 目录
obj-$(CONFIG_USB_PHY) += usb/
# 如果配置为 USB,则添加 usb 目录
obj-$(CONFIG_USB) += usb/
# 如果配置为 USB_SUPPORT,则添加 usb 目录
obj-$(CONFIG_USB_SUPPORT) += usb/
# 如果配置为 PCI,则添加 usb 目录
obj-$(CONFIG_PCI) += usb/
# 如果配置为 USB_GADGET,则添加 usb 目录
obj-$(CONFIG_USB_GADGET) += usb/
# 如果配置为 OF,则添加 usb 目录
obj-$(CONFIG_OF) += usb/
# 如果配置为 SERIO,则添加 input/serio 目录
obj-$(CONFIG_SERIO) += input/serio/
# 如果配置为 GAMEPORT,则添加 input/gameport 目录
obj-$(CONFIG_GAMEPORT) += input/gameport/
# 如果配置为 INPUT,则添加 input 目录
obj-$(CONFIG_INPUT) += input/
# 如果配置为 RTC_LIB,则添加 rtc 目录
obj-$(CONFIG_RTC_LIB) += rtc/
# 向 obj-y 添加 i2c、i3c、media 目录中的对象文件
obj-y += i2c/ i3c/ media/
# 如果配置为 PPS,则添加 pps 目录
obj-$(CONFIG_PPS) += pps/
# 向 obj-y 添加 ptp 目录中的对象文件
obj-y += ptp/
# 如果配置为 W1,则添加 w1 目录
obj-$(CONFIG_W1) += w1/
# 向 obj-y 添加 power 目录中的对象文件
obj-y += power/
# 如果配置为 HWMON,则添加 hwmon 目录
obj-$(CONFIG_HWMON) += hwmon/
# 如果配置为 THERMAL,则添加 thermal 目录
obj-$(CONFIG_THERMAL) += thermal/
# 如果配置为 WATCHDOG,则添加 watchdog 目录
obj-$(CONFIG_WATCHDOG) += watchdog/
# 如果配置为 MD,则添加 md 目录
obj-$(CONFIG_MD) += md/
# 如果配置为 BT,则添加 bluetooth 目录
obj-$(CONFIG_BT) += bluetooth/
# 如果配置为 ACCESSIBILITY,则添加 accessibility 目录
obj-$(CONFIG_ACCESSIBILITY) += accessibility/
# 如果配置为 ISDN,则添加 isdn 目录
obj-$(CONFIG_ISDN) += isdn/
# 如果配置为 EDAC,则添加 edac 目录
obj-$(CONFIG_EDAC) += edac/
# 如果配置为 EISA,则添加 eisa 目录
obj-$(CONFIG_EISA) += eisa/
# 如果配置为 PM_OPP,则添加 opp 目录
obj-$(CONFIG_PM_OPP) += opp/
# 如果配置为 CPU_FREQ,则添加 cpufreq 目录
obj-$(CONFIG_CPU_FREQ) += cpufreq/
# 如果配置为 CPU_IDLE,则添加 cpuidle 目录
obj-$(CONFIG_CPU_IDLE) += cpuidle/
# 向 obj-y 添加 mmc 目录中的对象文件
obj-y += mmc/
# 如果配置为 MEMSTICK,则添加 memstick 目录
obj-$(CONFIG_MEMSTICK) += memstick/
# 如果配置为 NEW_LEDS,则添加 leds 目录
obj-$(CONFIG_NEW_LEDS) += leds/
# 如果配置为 INFINIBAND,则添加 infiniband 目录
obj-$(CONFIG_INFINIBAND) += infiniband/
# 向 obj-y 添加 firmware 目录中的对象文件
obj-y += firmware/
# 如果配置为 CRYPTO,则添加 crypto 目录
obj-$(CONFIG_CRYPTO) += crypto/
# 如果配置为 SUPERH,则添加 sh 目录
obj-$(CONFIG_SUPERH) += sh/
# 如果架构不使用 gettimeofdayoffset
ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
# 向 obj-y 添加 clocksource 目录中的对象文件
obj-y += clocksource/
endif
# 如果配置为 DCA,则添加 dca 目录
obj-$(CONFIG_DCA) += dca/
# 如果配置为 HID,则添加 hid 目录
obj-$(CONFIG_HID) += hid/
# 如果配置为 PPC_PS3,则添加 ps3 目录
obj-$(CONFIG_PPC_PS3) += ps3/
# 如果配置为 OF,则添加 of 目录
obj-$(CONFIG_OF) += of/
# 如果配置为 SSB,则添加 ssb 目录
obj-$(CONFIG_SSB) += ssb/
# 如果配置为 BCMA,则添加 bcma 目录
obj-$(CONFIG_BCMA) += bcma/
# 如果配置为 VHOST_RING,则添加 vhost 目录
obj-$(CONFIG_VHOST_RING) += vhost/
# 如果配置为 VHOST_IOTLB,则添加 vhost 目录
obj-$(CONFIG_VHOST_IOTLB) += vhost/
# 如果配置为 VHOST,则添加 vhost 目录
obj-$(CONFIG_VHOST) += vhost/
# 如果配置为 VLYNQ,则添加 vlynq 目录
obj-$(CONFIG_VLYNQ) += vlynq/
# 如果配置为 GREYBUS,则添加 greybus 目录
obj-$(CONFIG_GREYBUS) += greybus/
# 如果配置为 STAGING,则添加 staging 目录
obj-$(CONFIG_STAGING) += staging/
# 向 obj-y 添加 platform 目录中的对象文件
obj-y += platform/
# 如果配置为 MAILBOX,则添加 mailbox 目录
obj-$(CONFIG_MAILBOX) += mailbox/
# 如果配置为 HWSPINLOCK,则添加 hwspinlock 目录
obj-$(CONFIG_HWSPINLOCK) += hwspinlock/
# 如果配置为 REMOTEPROC,则添加 remoteproc 目录
obj-$(CONFIG_REMOTEPROC) += remoteproc/
# 如果配置为 RPMSG,则添加 rpmsg 目录
obj-$(CONFIG_RPMSG) += rpmsg/
# 如果配置为 SOUNDWIRE,则添加 soundwire 目录
obj-$(CONFIG_SOUNDWIRE) += soundwire/
# Virtualization drivers
# 虚拟化驱动程序
# 如果配置为 VIRT_DRIVERS,则添加 virt 目录
obj-$(CONFIG_VIRT_DRIVERS) += virt/
# 如果配置为 HYPERV,则添加 hv 目录
obj-$(CONFIG_HYPERV) += hv/
# 如果配置为 PM_DEVFREQ,则添加 devfreq 目录
obj-$(CONFIG_PM_DEVFREQ) += devfreq/
# 如果配置为 EXTCON,则添加 extcon 目录
obj-$(CONFIG_EXTCON) += extcon/
# 如果配置为 MEMORY,则添加 memory 目录
obj-$(CONFIG_MEMORY) += memory/
# 如果配置为 IIO,则添加 iio 目录
obj-$(CONFIG_IIO) += iio/
# 如果配置为 VME_BUS,则添加 vme 目录
obj-$(CONFIG_VME_BUS) += vme/
# 如果配置为 IPACK_BUS,则添加 ipack 目录
obj-$(CONFIG_IPACK_BUS) += ipack/
# 如果配置为 NTB,则添加 ntb 目录
obj-$(CONFIG_NTB) += ntb/
# 如果配置为 POWERCAP,则添加 powercap 目录
obj-$(CONFIG_POWERCAP) += powercap/
# 如果配置为 MCB,则添加 mcb 目录
obj-$(CONFIG_MCB) += mcb/
# 如果配置为 PERF_EVENTS,则添加 perf 目录
obj-$(CONFIG_PERF_EVENTS) += perf/
# 如果配置为 RAS,则添加 ras 目录
obj-$(CONFIG_RAS) += ras/
# 如果配置为 USB4,则添加 thunderbolt 目录
obj-$(CONFIG_USB4) += thunderbolt/
# 如果配置为 CORESIGHT,则添加 hwtracing/coresight 目录
obj-$(CONFIG_CORESIGHT) += hwtracing/coresight/
# 向 obj-y 添加 hwtracing/intel_th 目录中的对象文件
obj-y += hwtracing/intel_th/
# 如果配置为 STM,则添加 hwtracing/stm 目录
obj-$(CONFIG_STM) += hwtracing/stm/
# 如果配置为 ANDROID,则添加 android 目录
obj-$(CONFIG_ANDROID) += android/
# 如果配置为 NVMEM,则添加 nvmem 目录
obj-$(CONFIG_NVMEM) += nvmem/
# 如果配置为 FPGA,则添加 fpga 目录
obj-$(CONFIG_FPGA) += fpga/
# 如果配置为 FSI,则添加 fsi 目录
obj-$(CONFIG_FSI) += fsi/
# 如果配置为 TEE,则添加 tee 目录
obj-$(CONFIG_TEE) += tee/
# 如果配置为 MULTIPLEXER,则添加 mux 目录
obj-$(CONFIG_MULTIPLEXER) += mux/
# 如果配置为 UNISYS_VISORBUS,则添加 visorbus 目录
obj-$(CONFIG_UNISYS_VISORBUS) += visorbus/
# 如果配置为 SIOX,则添加 siox 目录
obj-$(CONFIG_SIOX) += siox/
# 如果配置为 GNSS,则添加 gnss 目录
obj-$(CONFIG_GNSS) += gnss/
# 如果配置为 INTERCONNECT,则添加 interconnect 目录
obj-$(CONFIG_INTERCONNECT) += interconnect/
# 如果配置为 COUNTER,则添加 counter 目录
obj-$(CONFIG_COUNTER) += counter/
# 如果配置为 MOST,则添加 most 目录
obj-$(CONFIG_MOST) += most/
2. 解读
这段 Makefile 是 Linux 内核中设备驱动程序的构建脚本,旨在管理和编译不同的设备驱动子系统。它为每个配置选项指定了编译的文件或子目录,使内核可以在编译时根据不同的配置条件选择使用特定的功能模块。
(1)基本信息与结构
- 注释部分:开头部分包含了 SPDX-License-Identifier 和作者信息,以及撰写日期。这些信息有助于用户了解文件的许可证和作者。
# SPDX-License-Identifier: GPL-2.0
# Makefile for the Linux kernel device drivers.
# 15 Sep 2000, Christoph Hellwig <hch@infradead.org>
# Rewritten to use lists instead of if-statements.
(2) 主要功能与配置选项
obj-y
和obj-
的用法:obj-y
用于定义强制编译的子目录或源文件。所有以obj-y
开头的行中的子模块将被强制编译并链接到内核中。obj-$(CONFIG_OPTION)
用于条件编译,只有当CONFIG_OPTION
被选定(通常来源于内核配置文件.config
)时,相关的模块目录才会被编译。这种细粒度的控制允许内核能够针对不同硬件和功能量身定制。
(3)编译依赖与顺序
- 依赖关系:某些目录必须在其他目录之前被编译,因为它们依赖于前者的功能。例如:
# GPIO must come after pinctrl as gpios may need to mux pins etc
obj-$(CONFIG_PINCTRL) += pinctrl/
obj-$(CONFIG_GPIOLIB) += gpio/
这里表明 gpio
的编译需要在 pinctrl
之后。
(4) 模块功能的划分
代码中按照不同的功能划分了多个目录,下面逐个介绍这些模块的功能:
-
irqchip/
:中断控制器的管理,提高了系统硬件中断的处理能力。 -
bus/
:处理内核总线管理,包括不同总线接口的抽象和操作缺省。 -
phy/
:处理物理层接口函数,可能涉及到某些硬件特性。 -
pinctrl/
:控制引脚的设置和功能。 -
gpio/
:通用输入输出接口。 -
pwm/
:脉宽调制,主要用于控制硬件的功率输出特性。 -
pci/
:PCI总线相关代码,用于支持PCI硬件设备。 -
video/
,char/
,scsi/
,gpu/
等:由各种不同类型的硬件驱动模块组成,各自承担着不同的设备交互和控制任务。
(5) 虚拟化支持模块
# Virtualization drivers
obj-$(CONFIG_VIRT_DRIVERS) += virt/
obj-$(CONFIG_HYPERV) += hv/
在这部分代码中,添加了用于支持虚拟化的各种驱动模块。
(6)条件编译与架构适配
Makefile 的灵活性表现在它使用条件编译来适应不同的硬件架构。例如,
obj-$(CONFIG_PARISC) += parisc/
这条条件只有在 CONFIG_PARISC
被选中时,相关代码才会被编译,适应了支持 PA-RISC 架构的环境要求。
(7)平台依赖与框架
- SOC、平台、I2C 和数据存储模块的编译是按需进行的,以确保它们的代码和功能只有在相关配置被启用时才会编译进内核中。
(8)最终整合与排版
最后一部分 compiles 根据驱动的依赖关系和设置所需要的配置来整合所有非核心组件。在实际操作中,将根据用户在配置过程中的不同选项(例如 via make menuconfig
)来实施选择,生成适合用户要求和特定硬件的内核配置。
这份 Makefile 在内核的构建系统中发挥着至关重要的作用,通过清晰地指定哪些子模块需要在何时编译,使得 Linux 内核在覆盖广泛硬件的同时保持灵活性和可定制性。
3.1 Kconfig
该文件是 Linux 内核设备驱动程序配置选项的描述文件,它为内核的构建提供了可选的模块列表和选项。
1. 源码+注释
# SPDX-License-Identifier: GPL-2.0
menu "Device Drivers"
# 启动一个名为 “设备驱动程序” 的菜单,表示这个部分是设备驱动相关的配置选项。
# Keep I/O buses first
# 此部分提示应该优先处理 I/O 总线相关驱动。
# 源文件包含不同类型驱动的 Kconfig 配置文件
source "drivers/amba/Kconfig"
# 包含 AMBA(Advanced Microcontroller Bus Architecture)的设备驱动配置。
source "drivers/eisa/Kconfig"
# 包含 EISA(Extended Industry Standard Architecture)设备驱动程序的配置。
source "drivers/pci/Kconfig"
# 包含 PCI(Peripheral Component Interconnect)设备驱动配置。
source "drivers/pcmcia/Kconfig"
# 包含 PCMCIA(Personal Computer Memory Card International Association)驱动配置。
source "drivers/rapidio/Kconfig"
# 包含 RapidIO 驱动程序的配置。
source "drivers/base/Kconfig"
# 包含内核基本设备模型(Device Model)相关的驱动配置。
source "drivers/bus/Kconfig"
# 包含总线相关的驱动配置,管理多种总线的谈判和控制。
source "drivers/connector/Kconfig"
# 包含用于内核中软件或硬件连接的驱动配置。
source "drivers/gnss/Kconfig"
# 包含全球定位系统(GNSS)设备驱动的配置。
source "drivers/mtd/Kconfig"
# 包含 NAND 和 NOR 等 MTD(Memory Technology Device)闪存驱动的配置。
source "drivers/of/Kconfig"
# 包含 Open Firmware 驱动配置,这是许多嵌入式系统使用的一种标准接口。
source "drivers/parport/Kconfig"
# 包含并行端口的驱动程序配置。
source "drivers/pnp/Kconfig"
# 包含即插即用(Plug and Play)设备驱动的配置。
source "drivers/block/Kconfig"
# 包含块设备驱动程序的配置,处理硬盘和其他存储设备。
source "drivers/nvme/Kconfig"
# 包含 NVMe(Non-Volatile Memory Express)驱动程序的配置。
source "drivers/misc/Kconfig"
# 包含各种其他杂项设备的驱动配置。
source "drivers/ide/Kconfig"
# 包含 IDE(Integrated Drive Electronics)设备驱动配置。
source "drivers/scsi/Kconfig"
# 包含 SCSI(Small Computer System Interface)设备驱动程序配置。
source "drivers/ata/Kconfig"
# 包含 ATA(Advanced Technology Attachment)驱动程序的配置。
source "drivers/md/Kconfig"
# 包含多设备(Multiple Device)驱动配置,主要用于 RAID 和 LVM。
source "drivers/target/Kconfig"
# 包含目标驱动配置,SCSI 目标支持和其他存储控制管理功能。
source "drivers/message/fusion/Kconfig"
# 包含光纤通道和其他消息传递驱动程序的配置。
source "drivers/firewire/Kconfig"
# 包含 FireWire 设备驱动程的配置,这是高速度连接的一种技术。
source "drivers/macintosh/Kconfig"
# 包含与 Macintosh 设备相关驱动的配置。
source "drivers/net/Kconfig"
# 包含网络设备驱动程序的配置,可以管理以太网和 WLAN 等。
source "drivers/isdn/Kconfig"
# 包含 ISDN(Integrated Services Digital Network)相关设备驱动的配置。
source "drivers/lightnvm/Kconfig"
# 包含 LightNVM(NAND Flash固态存储)设备驱动的配置。
# input before char - char/joystick depends on it. As does USB.
# 输入类驱动程序应在字符设备驱动程序之前加载,
# 因为字符设备中包含的某些内容需要输入驱动。
source "drivers/input/Kconfig"
# 包含输入设备(如键盘、鼠标等)的驱动配置。
source "drivers/char/Kconfig"
# 包含字符设备驱动程序的配置,包括日志字符设备等。
source "drivers/i2c/Kconfig"
# 包含 I2C(Inter-Integrated Circuit)总线接口驱动的配置。
source "drivers/i3c/Kconfig"
# 包含 I3C(Improved Inter-Integrated Circuit)总线接口驱动的配置。
source "drivers/spi/Kconfig"
# 包含 SPI(Serial Peripheral Interface)驱动的配置。
source "drivers/spmi/Kconfig"
# 包含 SPMI(Serial Peripheral Model Interface)驱动的配置。
source "drivers/hsi/Kconfig"
# 包含 HSI(High-Speed Synchronous Link)设备驱动的配置。
source "drivers/pps/Kconfig"
# 包含 PPS(Pulse Per Second)设备驱动的配置,常用于时间测量。
source "drivers/ptp/Kconfig"
# 包含 PTP(Precision Time Protocol)驱动的配置。
source "drivers/pinctrl/Kconfig"
# 包含引脚控制器驱动程序的配置,用于管理 GPIO 引脚的复用和状态。
source "drivers/gpio/Kconfig"
# 包含 GPIO(通用输入输出)的驱动配置。
source "drivers/w1/Kconfig"
# 包含 1-Wire 设备驱动的配置。
source "drivers/power/Kconfig"
# 包含电源管理设备驱动的配置,如电源开关和电池监控功能。
source "drivers/hwmon/Kconfig"
# 包含硬件监控相关驱动的配置,如温度传感器。
source "drivers/thermal/Kconfig"
# 包含热管理驱动的配置,确保系统避免过热。
source "drivers/watchdog/Kconfig"
# 包含看门狗定时器设备驱动的配置,以防止系统崩溃及悬挂。
source "drivers/ssb/Kconfig"
# 包含 SSB(Simple Serial Bus)设备驱动的配置。
source "drivers/bcma/Kconfig"
# 包含 BCMA(Broadcom Common Access Bus Architecture)驱动的配置。
source "drivers/mfd/Kconfig"
# 包含 MFD(Multi-Function Device)设备驱动配置,处理多功能设备的支持。
source "drivers/regulator/Kconfig"
# 包含电压调节器驱动的配置。
source "drivers/media/Kconfig"
# 包含多媒体相关设备驱动的配置,如摄像头和音频设备。
source "drivers/video/Kconfig"
# 包含视频设备驱动的配置。
source "sound/Kconfig"
# 包含声音相关驱动的配置,音频设备和声卡支持。
source "drivers/hid/Kconfig"
# 包含 HID(Human Interface Device)相关设备驱动的配置。
source "drivers/usb/Kconfig"
# 包含 USB 设备驱动的配置,包括主机、设备和转接的支持。
source "drivers/mmc/Kconfig"
# 包含 MMC(MultiMediaCard)驱动的配置。
source "drivers/memstick/Kconfig"
# 包含记忆棒(Memory Stick)驱动的配置。
source "drivers/leds/Kconfig"
# 包含 LED Drievr 的配置,支持 LED 的点亮和调控。
source "drivers/accessibility/Kconfig"
# 包含可访问性设备驱动的配置,提升综合使用体验。
source "drivers/infiniband/Kconfig"
# 包含 InfiniBand 设备驱动的配置,常用于数据中心环境。
source "drivers/edac/Kconfig"
# 包含 EDAC(Error Detection and Correction)相关驱动的配置,用于内存故障检测。
source "drivers/rtc/Kconfig"
# 包含实时钟(RTC)的设备驱动配置,支持系统日期时间管理。
source "drivers/dma/Kconfig"
# 包含 DMA(Direct Memory Access)控制器驱动的配置。
source "drivers/dma-buf/Kconfig"
# 包含 DMA 缓冲区驱动的配置,使多个设备共享相同内存资源。
source "drivers/dca/Kconfig"
# 包含 DMA 凭证(DCA)相关驱动的配置。
source "drivers/auxdisplay/Kconfig"
# 包含辅助显示(Auxiliary Display)设备驱动资源的配置。
source "drivers/uio/Kconfig"
# 包含用户层 I/O 驱动程序(UIO)的配置,用于直接管理设备。
source "drivers/vfio/Kconfig"
# 包含 VFIO(Virtual Function I/O)驱动配置,用于虚拟化寄存器。
source "drivers/vlynq/Kconfig"
# 包含 VLYNQ 总线架构驱动的配置。
source "drivers/virt/Kconfig"
# 包含虚拟设备驱动程序界面的相关配置。
source "drivers/virtio/Kconfig"
# 包含 VirtIO 虚拟化设备支持的配置,常用于 KVM 和 QEMU。
source "drivers/vdpa/Kconfig"
# 包含 VDPA(Virtual Data Plane Acceleration)驱动的配置,优化虚拟化数据流。
source "drivers/vhost/Kconfig"
# 包含 VHOST 设备驱动及其管理的配置。
source "drivers/hv/Kconfig"
# 包含侧重于 Hyper-V 虚拟机管理器的驱动模块配置。
source "drivers/xen/Kconfig"
# 包含 Xen 虚拟化环境下的驱动支持相关配置。
source "drivers/greybus/Kconfig"
# 包含 Greybus 流量运输 状态设备驱动的配置。
source "drivers/staging/Kconfig"
# 包含用于测试和实验性设备驱动的配置,这些驱动正处在开发过程中的状态。
source "drivers/platform/Kconfig"
# 包含与特定平台(如歌曲设备、开发板等)相关的驱动程序配置。
source "drivers/clk/Kconfig"
# 包含时钟源及其管理的驱动程序配置。
source "drivers/hwspinlock/Kconfig"
# 包含硬件自旋锁管理文件的配置。
source "drivers/clocksource/Kconfig"
# 包含时钟源驱动支持的配置,提供时间管理功能。
source "drivers/mailbox/Kconfig"
# 包含邮件箱(Mailbox)支持的设备驱动配置。
source "drivers/iommu/Kconfig"
# 包含 IOMMU(输入输出内存管理单元)驱动的配置。
source "drivers/remoteproc/Kconfig"
# 包含远程处理器配置及相关驱动,用于网络和嵌入式高效并行计算环境。
source "drivers/rpmsg/Kconfig"
# 包含 RPMSG(Remote Procedure Call Messaging)设备相关驱动配置。
source "drivers/soundwire/Kconfig"
# 包含 SoundWire 音频接口标准支持的设备驱动配置。
source "drivers/soc/Kconfig"
# 包含系统单芯片(SoC)相关驱动配置。
source "drivers/devfreq/Kconfig"
# 包含动态频率调配(Dynamic Frequency Scaling) 驱动配置。
source "drivers/extcon/Kconfig"
# 包含外部连接(multipurpose docking) 设备关键驱动配置。
source "drivers/memory/Kconfig"
# 包含内存相关管理类驱动配置。
source "drivers/iio/Kconfig"
# 包含工业输入输出设备驱动的配置。
source "drivers/ntb/Kconfig"
# 包含 NTB(Non-Transparent Bridge)驱动的配置,支持数据高速传输协议。
source "drivers/vme/Kconfig"
# 包含 VME(Versatile Multilayer Bus)标准控制的驱动配置。
source "drivers/pwm/Kconfig"
# 包含 PWM(脉宽调制)设备驱动的配置。
source "drivers/irqchip/Kconfig"
# 包含中断控制器驱动的配置,处理系统中断的管理职责。
source "drivers/ipack/Kconfig"
# 包含 I-PACK 设备驱动的配置。
source "drivers/reset/Kconfig"
# 包含重置控制器的配置。
source "drivers/phy/Kconfig"
# 包含物理层接口设备驱动配置。
source "drivers/powercap/Kconfig"
# 包含电源限制器设备驱动配置。
source "drivers/mcb/Kconfig"
# 包含多通道总线配置,MCBUS 设备的驱动程序。
source "drivers/perf/Kconfig"
# 包含性能计算工具驱动程序的支持。
source "drivers/ras/Kconfig"
# 包含 RAS(Reliability, Availability and Serviceability)基础架构的设备驱动相关设置。
source "drivers/thunderbolt/Kconfig"
# 包含 Thunderbolt 连接设备驱动支持的配置。
source "drivers/android/Kconfig"
# 包含 Android 设备驱动支持的配置。
source "drivers/gpu/trace/Kconfig"
# 包含 GPU GPU 跟踪相关珠驱动配置。
source "drivers/nvdimm/Kconfig"
# 包含 NVDIMM(非易失性 DIMM)设备的驱动配置。
source "drivers/dax/Kconfig"
# 包含 DAX(Direct Access)驱动程序支持。
source "drivers/nvmem/Kconfig"
# 包含 NVMem(非易失内存)驱动相关设备的配置。
source "drivers/hwtracing/Kconfig"
# 包含硬件跟踪计算的驱动规则。
source "drivers/fpga/Kconfig"
# 包含现场可编程门阵列(FPGA)设备驱动配置。
source "drivers/fsi/Kconfig"
# 包含 FSI(框架协议)设备驱动的配置。
source "drivers/tee/Kconfig"
# 包含 TEE(信任执行环境)设备驱动配置。
source "drivers/mux/Kconfig"
# 包含多重选择主控设备的配置。
source "drivers/opp/Kconfig"
# 包含操作点(OPP)管理的配置,涉及电能的分配与使用。
source "drivers/visorbus/Kconfig"
# 包含 VisorBus 驱动的配置,即使在跨 Windows 类型玩家中支持通通信。
source "drivers/siox/Kconfig"
# 包含 SiOX 驱动支持的配置,处理特定设备管理。
source "drivers/slimbus/Kconfig"
# 包含 SlimBus设备支持的驱动设置进行配置。
source "drivers/interconnect/Kconfig"
# 包含在不同设备间的数据生成链接的配件厂商消息支持。
source "drivers/counter/Kconfig"
# 包含并发计数最大装机设备的驱动的配置ٹ,
source "drivers/most/Kconfig"
# 包含 MOST(Media Oriented Systems Transport)设备驱动的配置。
endmenu
# 结束“设备驱动程序”菜单。
2. 解读
本文件用于配置 Linux 内核的设备驱动程序部分。它为各类设备驱动提供了编译选项,让从开发者到最终用户能够选择需要的模块和驱动。
(1) 文件头和菜单开始
# SPDX-License-Identifier: GPL-2.0
menu "Device Drivers"
- SPDX License: 这一行声明了该文件的许可协议,指定接受GPL-2.0许可证,确保代码的开源性和自由使用等措施。
- menu “Device Drivers”: 启动一个名为“设备驱动程序”的菜单,表示以下所有条目都与内核设备驱动程序相关,提高用户针对性选择。
(2)I/O 总线的管理
# Keep I/O buses first
- 这部分注释说明里面首先列出了I/O总线相关的驱动,该做法确保设备驱动在核心内汇聚和匹配相应硬件之前,提高驱动间互操作性的兼容性。
(3)驱动源文件的解析
Kconfig文件使用了多个source
语句,它们用于包含特定子模块的配置。这些目录一般指向不同类型的设备驱动程序的配置。不逐个详细介绍,只做分块处理即可,这样可以让说明更有条理。以下是一些主要的设备驱动模块和组件。
基础架构和总线管理
source "drivers/amba/Kconfig"
source "drivers/eisa/Kconfig"
source "drivers/pci/Kconfig"
source "drivers/pcmcia/Kconfig"
source "drivers/rapidio/Kconfig"
source "drivers/base/Kconfig"
source "drivers/bus/Kconfig"
- AMBA: ARM的AMBA总线架构支持。
- EISA: 扩展行业标准架构,附加的设备管理和解析。
- PCI: 通用的 PCI 接口,描述如何支持 PCI 设备。
- PCMCIA: 便携计算机记忆卡国际协会,用于老设备支持。
- RapidIO: 针对特定异构设备支持超高速数据传输。
- 基础模块与总线: 处理基础设施功能,如设备模型、设备总线管理等。
存储及数据传输相关
source "drivers/mtd/Kconfig"
source "drivers/block/Kconfig"
source "drivers/nvme/Kconfig"
source "drivers/ide/Kconfig"
source "drivers/scsi/Kconfig"
source "drivers/ata/Kconfig"
source "drivers/md/Kconfig"
source "drivers/target/Kconfig"
- MTD: 代表各种闪存设备驱动。
- 块设备: 专门针对块设备支持,如物理磁盘驱动。
- NVMe: 高速固态存储接口支持。
- SCSI和IDE: 常见存储接口,每种类型描述其设备特性。
- MD: 对 RAID 等配置的多设备阵列支持。
- Target layer: 存储协议下的实现。
行业接口与辅助服务
source "drivers/message/fusion/Kconfig"
source "drivers/firewire/Kconfig"
source "drivers/macintosh/Kconfig"
source "drivers/net/Kconfig"
source "drivers/infiniband/Kconfig"
- 包括消息传递、FireWire和网络设备,这确保系统能够直接和多种外部设备进行通信和操作。
输入与输出设备
source "drivers/input/Kconfig"
source "drivers/char/Kconfig"
source "drivers/gpio/Kconfig"
source "drivers/leds/Kconfig"
- 涉及到输入设备(如键盘、鼠标)控制,以及通用脚位和LED输出控制有关逻辑。
(4)管理机、电源和其他监控
source "drivers/power/Kconfig"
source "drivers/hwmon/Kconfig"
source "drivers/thermal/Kconfig"
source "drivers/watchdog/Kconfig"
- 定义了电源管理设备、硬件监测、热管理及进行实时系统状态监控的手段,通过这些驱动保障系统的稳定性和可靠性。
(5)扩展功能和新兴技术支持
source "drivers/usb/Kconfig"
source "drivers/virtio/Kconfig"
source "drivers/vhost/Kconfig"
source "drivers/gpu/trace/Kconfig"
source "drivers/fsi/Kconfig"
- USB驱动及虚拟化技术 supported,通过这些来支持现代计算环境与外设的接合点,并关注新兴技术的发展。
(6) 其他模块与终结
文件的最后部分继续添加其他驱动模块的配置:
source "drivers/most/Kconfig"
source "drivers/thunderbolt/Kconfig"
source "drivers/clocksource/Kconfig"
source "drivers/mmc/Kconfig"
source "drivers/tee/Kconfig"
- 成熟硬件—如Thunderbolt、内存卡、时钟源支持等,提供了系统在通讯传输时的扩展性和效率。
(7) 结束
endmenu
最后,为上面定义的设备驱动程序的菜单结束这个阶段,确保后续 Kconfig 定义分隔明确。
整个 Kconfig 文件负责定义多层次的设备驱动模块,确保各驱动之间的兼容性,增强了不同硬件在内核中间通信和支持的灵活性。这一套清晰的分类帮助Linux内核运行过程中保持高效性、可定制性,为多种硬件平台提供支持。开发者及用户通过编译时选择配置,需要的驱动高效集成进生命线操作系统。
四、Linux内核源码编译过程
4.1 顶层Makefile与子目录下Makefile的关系
在Linux内核的Makefile编译过程中,顶层Makefile通过递归的方式与底层子目录的Makefile协同工作,构建整个内核映像。
-
顶层Makefile初始化:首先执行顶层Makefile,读取内核配置(如
.config
),定义全局变量(如obj-y
、obj-m
)、编译工具链、架构相关参数等。 -
递归调用子目录Makefile:顶层Makefile通过
$(MAKE) -C dir
命令(或subdir-y
/subdir-m
变量)递归进入子目录,调用各自的Makefile。子目录的Makefile通常通过obj-y
或obj-m
声明需要编译的目标文件(.o
)或模块,并可能进一步向下递归。 -
依赖关系传递:子目录Makefile中定义的
obj-y
(内置内核目标)或obj-m
(可加载模块)会汇总到顶层变量中。例如,obj-y += dir/file.o
会将依赖传递给顶层,最终由顶层Makefile统一生成built-in.a
静态库或vmlinux
。 -
链接阶段:顶层Makefile根据所有子目录汇总的
obj-y
目标文件,链接生成内核映像(如vmlinux
)。模块(obj-m
)则编译为独立.ko
文件。
关键点:
- 递归构建:通过
$(MAKE) -C
逐层进入子目录,依赖关系通过obj-y
/obj-m
向上传递。 - 变量继承:子目录Makefile继承顶层定义的变量(如
CC
、CFLAGS
),并可覆盖局部配置。 - 自动生成规则:通过
Makefile.build
等脚本隐式处理.c
→.o
的编译规则,减少重复代码。
整个过程通过变量传递和递归调用实现模块化编译,最终由顶层Makefile完成全局链接。
4.2 如何编译出一个完整的内核镜像呢?
要编译出一个完整的 Linux 内核镜像,需要准备编译环境,包括安装必要的工具链(如 GCC、Make、Binutils)和依赖库(如 libncurses、OpenSSL)。
然后获取内核源代码,可以通过官方仓库下载稳定版本或使用 Git 克隆主线开发分支。进入内核源码目录后,运行 make menuconfig
(或 make xconfig
/make defconfig
)配置内核选项,选择需要的驱动、文件系统支持和内核特性,并保存为 .config
文件。
接着执行 make
命令开始编译,这会依次处理顶层 Makefile 和子目录 Makefile,生成目标文件并最终链接成内核映像(如 vmlinux
或 bzImage
)。
编译完成后,内核镜像通常位于 arch/<架构>/boot/
目录下,例如 arch/x86/boot/bzImage
。如果需要安装到系统,可运行 make modules_install
安装内核模块,再使用 make install
部署内核镜像和初始 RAM 磁盘(initramfs)。
整个过程依赖正确的配置和工具链支持,确保目标架构和交叉编译环境(如适用)匹配。