??Linux 最初是为基于 32 位 x86 架构的 PC 开发的。如今,它已经可以工作在了 Compaq Alpha AXP、Sun SPARC、Motorola 68000、PowerPC、ARM、Hitachi SuperH、IBM S/390、MIPS、HP PA-RISC,Intel IA-64 等众多平台之上。
??Linux Kernel 将功能划分为了各种子系统,子系统之间相对独立。其中,最为核心的应该就是下面的 5 个子系统,这 5 大子系统也是在众多书籍中的常客。但是,随着 Linux Kernel 的不断发展,新的子系统也在不断出现。
??FHS(Filesystem Hierarchy Standard,文件系统层次结构标准)是多数 Linux 发行版采用这种文件组织形式,FHS 定义了系统中每个区域的用途、所需要的最小构成的文件和目录同时还给出了例外处理与矛盾处理。
??FHS 是根据以往无数 Linux 用户和开发者的经验总结出来的,FHS 是依据文件系统使用的频繁与否以及是否允许用户随意改动而持续更新的。FHS 由 Linux 基金会维护,最新版本是 2015 年 6 月 3 日发布的 3.0。
-
/bin:Binaries 的缩写,存放一些可以被 root 与一般用户所使用的可执行程序,例如 cat
、chmod
、chown
、date
、mv
、mkdir
、cp
、bash
等常用的指令。
Ubuntu 中,它是一个指向 /usr/bin
的硬链接
-
/boot:放置开机会使用到的文件,包括 Linux 核心文件以及开机菜单与开机所需配置文件等等。
操作系统内核必须存在根目录或者 /boot
目录
-
/dev:在 Linux 系统上,任何设备与周边设备都是以文件的型态存在于这个目录当中的。 通过存取这个目录下面的某个文件,就等于存取某个设备了。
-
/etc:系统主要的配置文件几乎都放置在这个目录内,例如人员的帐号密码档、各种服务的启始档等等。一般来说,这个目录下的各文件属性是可以让一般使用者查阅的, 但是只有 root 有权修改。
- /etc/opt:这个目录在放置
/opt
中的第三方协力软件 的相关配置文件 - /etc/sgml:与 SGML 格式有关的各项配置文件
- /etc/X11:与 X Window 有关的各种配置文件都在这里,例如, X Server 的配置文件 xorg.conf。
- /etc/xml:与 XML 格式有关的各项配置文件
-
/lib:系统的函数库非常的多,而 /lib 放置的则是在开机时会用到的函数库, 以及在 /bin 或 /sbin 下面的可执行程序会调用的函数库而已。
- Ubuntu 中,它是一个指向
/usr/bin
的硬链接 - 与不同架构对应,lib 通常分为 lib32、lib64 等
- /lib/modules/:主要放置可抽换式的核心相关模块(驱动程序)。
-
/media:media 是“媒体”的英文,用于放置的就是可移除的设备啦! 包括软盘、光盘、DVD 等等设备都暂时挂载于此。常见的文件名有:/media/floppy
、/media/cdrom
等等。
-
/mnt:暂时挂载某些额外的设备一般放置到这个目录中。在古早时候,这个目录的用途与/media相同,有了 /media
之后,这个目录就用来暂时挂载用了。
-
/opt:用于存放那些第三方非系统软件。常见的就是那些 GUI 软件,例如那些基于 KDE 的 GUI 程序。
在以前的 Linux 系统中,经常是放置在 /usr/local
目录下!
-
/run:早期的 FHS 规定系统开机后所产生的各项信息应该要放置到 /var/run
目录下,新版的 FHS 则规范到 /run
下面。 由于 /run
可以使用内存来仿真,因此性能上会好很多!
-
/sbin:Linux 有非常多指令是用来设置系统环境的,这些指令只有 root 才能够利用来“设置”系统,其他使用者最多只能用来“查询”而已。 放在 /sbin
下面的为开机过程中所需要的,里面包括了开机、修复、还原系统所需要的指令。 常见的指令包括:fdisk
、fsck
、ifconfig
、mkfs
等等。
Ubuntu 中,它是一个指向 /usr/sbin
的硬链接
-
/srv:可以视为 service 的缩写,是一些网络服务启动之后,这些服务所需要取用的数据目录。 常见的服务例如 WWW、FTP 等等。例如,WWW 服务器需要的网页数据就可以放置在 /srv/www/
里面
-
/tmp:这是让一般使用者或者是正在执行的程序暂时放置文件的地方。 这个目录是任何人都能够存取的,重要数据不可放置在此目录!
FHS 甚至建议在开机时,应该要将 /tmp
下的数据都删除。
-
/usr:是 Unix Software Resource 的缩写, 也就是 Unix 操作系统软件资源所放置的目录。FHS 建议所有软件开发者,应该将他们的数据合理的分别放置到这个目录下的次目录,而不要自行创建该软件自己独立的目录。
-
/usr/bin:非必要的命令二进制文件(在单用户模式下不需要);面向所有用户。
-
/usr/include:各种标准的头文件
-
/usr/lib:/usr/bin
和 /usr/sbin
中的可执行程序使用的库文件。
与不同架构对应,lib 通常分为 lib32、lib64 等
-
/usr/local:特定于本主机的本地数据的三级层次结构,通常具有进一步的子目录(例如,bin,lib,Share)。那些使用源码方式安装(make)的软件通常就放到这个目录下。
-
/usr/sbin:非必要的系统二进制文件(例如,各种网络服务的守护进程)。
-
/usr/share:与体系结构无关的(共享)数据。
-
/usr/src:该Linux 发行版使用的 Kernel 源代码
-
/var:主要针对常态性变动的文件,包括高速缓存(cache)、登录文件(log file)以及某些软件运行所产生的文件, 包括程序文件(lock file、run file),或者例如 MySQL 数据库的文件等等。
- /var/cache:应用程序缓存数据。此类数据是由于耗时的 I/O 或计算而在本地生成的。应用程序必须能够重新生成或还原数据。可以删除缓存的文件而不会丢失数据。
- /var/lib:状态信息。程序在运行时修改的持久性数据(例如,数据库、打包系统元数据等)
- /var/lock:锁定文件。跟踪当前正在使用的资源的文件。
- /var/log:日志文件。里面有各种日志。
- /var/mail:邮箱文件。在某些发行版中,这些文件可能位于已弃用的
/var/spool/mail
中 - /var/opt:存储在
/opt
中的附加程序包中的变量数据。 - /var/run:运行时变量数据。此目录包含自启动系统以来描述系统的系统信息数据。在 FHS 3.0 中,
/var/run
被 /run
取代,但为了向后兼容,系统应该继续提供 /var/run
目录或者提供从 /var/run
到 /run
的符号链接。 - /var/tmp:在重新启动之间要保留的临时文件
-
/home:这是系统默认的使用者主文件夹(home directory)。新增一个一般使用者帐号时, 默认的使用者主文件夹都会规范到这里来。
通常使用 ~
表示。
-
/root:系统管理员(root)的主文件夹。之所以放在这里,是因为如果进入单人维护模式而仅挂载根目录时, 该目录就能够拥有 root 的主文件夹,所以我们会希望 root 的主文件夹与根目录放置在同一个分区中。
-
/lost+found:这个目录是使用标准的 ext2/ext3/ext4 文件系统格式才会产生的一个目录,目的在于当文件系统发生错误时, 将一些遗失的片段放置到这个目录下。如果使用的是 xfs 文件系统的话,就不会存在这个目录了!
-
/proc:这个目录本身是一个虚拟文件系统(virtual filesystem),他放置的数据都是在内存当中, 例如系统核心、行程信息(process)、周边设备的状态及网络状态等等。因为这个目录下的数据都是在内存当中, 所以本身不占任何硬盘空间!比较重要的文件例如:/proc/cpuinfo
、/proc/dma
、/proc/interrupts
、 /proc/ioports
、 /proc/net/*
等等。
-
/sys:这个目录其实跟 /proc
非常类似,也是一个虚拟的文件系统,主要也是记录核心与系统硬件信息较相关的信息。 包括目前已载入的核心模块与核心侦测到的硬件设备信息等等。这个目录同样不占硬盘容量。
-
arch:即 architecture 的缩写,用于存放不同 CPU 体系架构的代码。每种 CPU 体系结构都放到对应的子目录中。官方对于各种架构的说明文档:https://www.kernel.org/doc/html/latest/arch.html。
-
alpha:原名 Alpha AXP,是由数字设备公司(DEC)开发的 64 位精简指令集计算机(RISC)指令集架构(ISA)。
-
arc:最初由 ARC International 设计的一系列 32 位和 64 位精简指令集计算机(RISC)中央处理器(CPU),采用 16/32 位 ARCompact 指令集架构 (ISA)。
2009 年,ARC International 被 Virage Logic 收购。2010 年,Virage 被 Synopsys 收购,ARC 处理器成为 Synopsys DesignWare 系列的一部分
-
arm:32 位 ARM IP 系列
-
arm64:64 位 ARM IP 系列,ARMv8 开始支持 64 位架构。
-
csky:中天微 IP 系。2018 年 4 月 20 日,中天微被阿里巴巴集团全资收购。国内芯片如 方寸微电子的 T6x0 系列。
-
hexagon:高通公司一系列数字信号处理器(DSP)产品的品牌名字,也被称为 QDSP6。每个版本的 Hexagon 都有一个指令集和一个微架构。主要用于高通骁龙芯片,例如智能手机,汽车,可穿戴设备和其他移动设备,也用于蜂窝电话网络的组件。
-
ia64:Intel 安腾(itanium architecture)系列 CPU,由英特尔与惠普共同开发,与 x86 及 x86-64 并不兼容,目前基本已经死的差不多了。
Linus Torvalds 曾在一篇代码评论中透露,计划移除对 Intel 安腾处理器的支持。
-
m68k:摩托罗拉的 68000 系列 CPU,是一系列 32 位复杂指令集计算机 (CISC) 微处理器。上世纪 80 年代是英特尔 x86 微处理器的主要竞争对手。虽然没有现代台式计算机基于 680x0 系列的处理器,但衍生处理器仍然广泛用于嵌入式系统。
-
microblaze:MicroBlaze 嵌入式软核是一个被 Xilinx 公司优化过的可以嵌入在 FPGA 中的 RISC 处理器软核。
MicroBlaze Soft Processor Core
-
mips:MIPS (Microprocessor without Interlocked Pipelined Stages) 架构的精简指令集计算机 (RISC) 微处理器。MIPS 架构是由 MIPS Technologies 开发的,除了有自己的芯片,还卖 IP 供第三方开发芯片。
2021 年 3 月,Wave Computing 宣布 MIPS 架构的开发已经停止。该公司已加入 RISC-V 基金会,未来的处理器设计将基于 RISC-V 架构。
-
nios2:Altera 推出的 Nios II 系列 32 位 RISC 嵌入式处理器。主要用于 FPGA,与 MicroBlaze 竞争。
-
openrisc:OpenCores 组织提供的基于 GPL 协议的开放源代码的 RISC(精简指令集计算机)处理器。
目前国内已有基于 OR1200 核的 SOC 产品,比如,华视奇半导体有限公司推出的 Vivace Semiconductor 多媒体处理芯片
-
parisc:由惠普开发的指令集架构(ISA),其中 PA 代表 Precision Architecture。该设计也称为惠普精密架构的 HP / PA。PA-RISC 已被由惠普和英特尔联合开发的 Itanium(最初是 IA-64)ISA 取代
-
powerpc:1991 年 Apple-IBM-Motorola 联盟创建的简化指令集计算机(RISC)指令集架构(ISA),自2006年以来一直被命名为Power ISA。
-
riscv:一个基于精简指令集(RISC)原则的开源指令集架构(ISA),RISC-V 目前比较火,很多公司都在设计 RISC-V 架构的芯片。
-
s390:IBM System/390 32 位架构指令集,通常 用 s390x 表示 64 位 z/架构
-
sh:SuperH 是 90 年代早期由日立开始开发,是一种性价比、体积小、功耗低的32位、64位的RISC嵌入式微处理器
-
sparc:1987 年,SUN 公司开发的 RISC 微处理器
-
um:User-mode Linux (UML) 是 Linux 内核到其自己的系统调用接口的体系结构端口,它使多个基于 Linux 内核的虚拟操作系统(称为来宾)能够在普通 Linux 系统(称为主机)中作为应用程序运行。
-
x86:x86 架构系列
-
xtensa:Tensilica 公司的 IP,主要领域是 HiFi 音频、 语音及视觉DSP。2013年, 被 Cadence Design Systems 收购并成为的一个部门。
这些 CPU 架构子目录中,又进一步分解为下一级子目录。其中就有些功能相似的同名目录:
-
block:该目录下放的是一些 linux 存储体系中关于块设备管理的代码。在 linux 中 block 表示块设备(以块(多个字节组成的整体,类似于扇区)为单位来整体访问),例如 SD 卡、iNand、Nand、硬盘等都是块设备。几乎可以认为块设备就是存储设备。
??最初 block 层代码一部分位于 drivers 目录,一部分位于 fs 目录。从 2.6.15 开始,block 层的核心代码就被提取出来放在顶层的 block 目录中。
-
certs:存储了认证和签名相关代码。证书和签名文件用于给模块签名,并允许内核加载签名模块,有助于防止恶意代码与内核模块一起运行。
-
crypto:该目录下是 Kernel 实现的一套通用 Cryptographic 算法框架,是一个独立的子系统(Cryptographic API),目前,由 Herbert Xu 维护。它实现了对算法的统一管理,并提供出统一的数据处理接口给其他子系统使用。
-
Documentation:这个目录下是 Kernel 的文档,它使用的是 Sphinx 搭建的文档系统。Sphinx 文档系统可以生成 html、pdf 等格式。Kernel 文档在线托管地址是:https://docs.kernel.org/,在线版文档就是使用 Sphinx 基于该目录下的文档源码文件生成的 html 格式的文档,两者内容并没有区别。
??Sphinx 是基于 Python 的,使用的是 reStructuredText 语言格式,文件扩展名通常是 .rst。Sphinx 文档系统使用 make 命令来生成发布的文档,在 Documentation 下执行 make htmldocs
命令,就会生成一个 output 的目录,其中就包含了生成的文档。
- Kernel 源码根目录的 Makefile 也有生成文档的目标,它会直接调用
Documentation/Makefile
文件 - 依赖工具: sudo apt install python3-pip 、sudo pip install -U Sphinx sphinx_rtd_theme graphviz
-
drivers:该目录中是系统中所有的设备驱动程序。它又进一步根据设备类型划分成几类设备驱动,每一种有对应的子目录,如声卡的驱动对应于 drivers/sound
;block 下为块设备驱动程序。
-
fs:fs 就是 file system,该目录中是虚拟文件系统(VFS)和各个不同文件系统的代码所在的目录。其中每个逻辑文件系统 , 都在 fs 目录下有对应的目录 , 如 ext2 , ext3 , ext4 , fat , nfs 等
-
include:该目录包括编译核心所需要的大部分头文件,例如与平台无关的头文件在 include/linux 子目录下,与 intel cpu 相关的头文件在 include/asm-i386 子目录下,而 include/scsi 目录则是有关 scsi 设备的头文件目录。每种 CPU 架构特有的一些头文件则位于 arch 目录具体架构的 include 目录下(例如,arch/arm/include
)。
- uapi:共用的用户态头文件。
- 在内核安装之后,uapi 包含文件就变成了顶级的
/usr/include/linux/*
文件。 - Kernel 3.5 版本时,David Howells 提出将用户态 API 单独存放,以解决头文件递归引用的问题。并在 3.7 版本被合并到 Mainline 仓库。
-
init:init是初始化的意思,这个目录下的代码就是linux内核启动时初始化内核的代码。
-
ipc:ipc就是inter process commuication,进程间通信,里面都是linux支持的IPC的代码实现
-
kernel:kernel 就是内核,就是linux内核,所以这个文件夹下放的就是内核本身需要的一些代码文件
-
lib:该目录下包含一些与架构无关的公用的函数(例如,排序、校验和、压缩和解压缩、位图操作等),以供内核的其他模块调用。与处理器结构相关的库代码(例如,strlen、memcpy 等)被放在 arch/*/lib/
目录下。
??注意这里的库函数和 C 语言的库函数不一样的。在内核编程中是不能用 C 语言标准库函数,这里的 lib目录下的库函数就是用来替代那些标准库函数的。例如,在内核中要打印信息时不能用 printf,而要用 printk,这个 printk 就在 lib 目录下。
-
LICENSES:该目下存放了 Kernel 所遵循的许可证原始文件。我们都知道,Linux Kernel 是基于 GPLv2 许可证进行开源的。GPLv2 许可证是涵盖整个内核分发的许可证,但是具体到某个源码文件时,可以有不同的许可证。除此之外,个人文件可以在双重许可下提供。但是,一个前提是这些不同的的许可证必须兼容 GPLv2。
??一个例外就是系统调用:编写用户空间程序时肯定得包含 Kernel 的源文件,根据 GPLv2 传染性意味着别人的用户程序也得开源,显然不合适。为此,在 LICENSES/exceptions/Linux-syscall-note
中显式描述了这个情况。所以,Linux Kernel 的许可证准确的应该叫 SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note 才更合适。
https://docs.kernel.org/process/license-rules.html
??在 Kernel 中,源码文件的许可方式是根据文件类型的不同,在文件的开头以注释的形式显示增加 SPDX-License-Identifier: GPL-2.0-only
。Linux Kernel 要求在所有源文件中提供精确的 SPDX 标识符且标识的许可证必须是在 LICENSES 目录下已经存在的。
??SPDX 许可证标识符是计算机可解析的,是贡献文件内容所依据的许可证的精确简写。SPDX 许可证标识符由 Linux 基金会的 SPDX 工作组管理,并已得到整个行业的合作伙伴、工具供应商和法律团队的同意。有关详细信息参阅 https://spdx.org/。
-
mm: memory management,内存管理,linux 的内存管理代码都在这里
-
net:该目录下是网络相关的代码,譬如TCP/IP协议栈等都在这里。
-
samples:示例
-
scripts:这个目录下是一些开发 Kernel 本身使用的脚本文件,linux 内核工作时是不会使用的。主要是用来辅助对 linux 内核进行开发(配置、编译等)。
-
security:安全相关的代码。
-
sound:音频处理相关的。
-
tools:linux 中用到的一些有用工具
-
usr:目录下是 initramfs 相关的,和 linux 内核的启动有关
-
virt:这个目录下是 KVM (Kernel Virtual Machine) 管理程序的相关代码
-
.clang-format:.clang-format
是 LLVM 提供的针对 C/C++ 代码的格式化工具 clang-format
的配置文件,包含了一些适用于 Kernel 内核编码风格的 clang-format
的选项。当我们在 Kernel 源码根目录下使用 clang-format
时,就会自动加载该配置文件中的配置项。.clang-format
中配置的代码风格如下所示:
??.clang-format
中的配置只是尽可能多的去符合 Kernel 的编码风格。当前的 Kernel 的代码中,很多代码格式都不符合 .clang-format
中配置的要求(上图中黄色表示不符合的提示)。并且,某些子系统的代码风格本身就与整体 Kernel 代码风格也存在差异。
- Linux kernel coding style
clang-format
在主流 Linux 发行版中都有提供,可以非常方便的进行安装。例如,Ubuntu 中 sudo apt install clang-format
-
.cocciconfig:.cocciconfig
是 Linux 下的一个可定制程度很高的静态代码分析工具 Coccinelle 的配置文件,包含对 Coccinelle 的配置参数。在 Kernel 源码的 script 目录下提供了一个脚本 script/coccicheck
供开发者使用 Coccinelle 来检测 kernel 代码。此外,根目录的 Makefile 中也专门创建了一个 coccicheck 目标。因此,可以直接使用 make coccicheck
。
??Coccinelle 运行依赖 Spatch
程序 和 Semantic Patch Language 文件(扩展名 *.cocci
文件)。当我们执行 script/coccicheck
时,就会调用 Spatch 使用 script/coccinelle/xxx/.cocci
语法文件来分析代码,每一个 .cocci
都是一个类型的错误检测。
- Linux Kernel 介绍文档:https://docs.kernel.org/dev-tools/coccinelle.html
- 官网:coccinelle.lip6.fr
- 源码:https://github.com/coccinelle/coccinelle
- 主流 Linux 发行版都会提供该工具。例如,Ubuntu:
sudo apt install coccinelle
-
.get_maintainer.ignore:用于在使用 scripts/get_maintainer.pl
获取 Kernel 维护者的时候忽略此文件中列出的人员。
-
.gitattributes:.gitattributes
是 Git 的配置文件之一,文件中的每一行定义一个/类文件/路径的若干属性,基本格式:文件 属性1 属性2 ...
。其中,文件名支持使用通配符(例如,*.c
表示所有 c 语言源码文件);属性有很多,常用的有 text、diff、eol 等。
git 官方文档:https://git-scm.com/docs/gitattributes
-
.gitignore:.gitignore
文件用来告诉 Git 忽略被记录在 .gitignore
文件里的文件或文件夹的改动。被忽略的文件是不会被放入到远程仓库里的。注意,如果文件已经存在于远程仓库中,是无法通过 .gitignore
文件来忽略的
git 官方文档:https://git-scm.com/docs/gitignore
-
.mailmap:这个文件主要是记录了一些大神维护内核的名字和邮箱。git-shortlog 使用这个列表来修复 git 归档文件中一些糟糕的名称翻译,要么是因为作者的全名被弄乱了,要么是因为作者的书写方式不总是相同,导致同一个人的贡献看起来不是这样或显示得不好。也允许旧的电子邮件地址映射到新的电子邮件地址。
-
COPYING:Kernel 的版权说明,指出了 Kernel 使用的许可证。
-
CREDITS:自 1994 年 3 月 13 日起,CREDITS 文件就开始被包含在了 Kernel 根目录下。该文件中记录了为 Kernel 做过贡献的开发者的主要贡献领域、电子邮件和实际地址以及其他相关数据等基本信息。
-
Kbuild 和 Kconfig:K 指的是 Kernel,Kbuild 和 Kconfig 是 Kernel 的配置及编译构建系统。Kconfig 用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个 Kconfig 文件,生成配置界面供开发人员配置内核,最后生成配置文件 .config
;Kbuild 则用于编译内核。
- Kernel Build System
- Kbuild 和 Kconfig 就是对 Make 的进一步扩展
-
MAINTAINERS:这个文件列出了 Kernel 中每个子系统的维护者的基本信息。同时也给出了如何正确提交对内核的更改(PATCH)。
-
Makefile:它是 Kernel 配置及构建的入口。Kernel 使用 make 系统来管理构建过程。
-
README:这个文件就是一个简单的对于 Kernel 的自我介绍。由于 Kernel 包含了详细的文档,因此,该文件中并没有啥实质性的内容,就是作为一个入口,导航的其他介绍文档。
??我这里使用主机操作系统是 Ubuntu 22.04 LTS,交叉编译工具链是 ARM 发布的最新版 11.2 版。在编译 Kernel 的过程中,我们可能还需要安装其他一些依赖工具,这个在后面用到的时候缺啥装啥就可以(出现各种错误的时候再安装相应工具即可)。
??注意,由于在之前在编译 U-Boot 时,我已经安装了大部分构建过程中需要的工具,因此,这里可能没有太多需要重新安装的工具了。如果出现错误,具体见博文 U-Boot 之一 零基础编译 U-Boot 过程详解 及 编译后的使用说明 应该有解决方法。