大家好,这里是 Lucifer三思而后行,公众号赠书福利活动 正式开启。
《图解Linux内核(基于6.x)》
一、前言
本文是 Linux 内核源码分析系列的专业,会以内核的核心功能为出发点,描述 Linux 内核的整体架构,以及架构之下主要的软件子系统。之后,会介绍 Linux 内核源文件的目录结构,并和各个软件子系统对应。
二、Linux内核的核心功能
如下图所示,Linux 内核只是 Linux 操作系统一部分:
对下,它管理系统的所有硬件设备;
对上,它通过系统调用,向 Library Routine(例如 C 库)或者其它应用程序提供接口;
因此,其核心功能就是:
管理硬件设备
供应用程序使用
而现代计算机(无论是PC还是嵌入式系统)的标准组成,就是 CPU、Memory(内存和外存)、输入输出设备、网络设备和其它的外围设备。所以为了管理这些设备,Linux 内核提出了如下的架构。
三、Linux内核的整体架构
3.1 整体架构和子系统划分
上图说明了 Linux 内核的整体架构。根据内核的核心功能,Linux 内核提出了 5 个子系统,分别负责如下的功能:
Process Scheduler:
也称作进程管理、进程调度。
负责管理 CPU 资源,以便让各个进程可以以尽量公平的方式访问 CPU。
Memory Manager:
内存管理。
负责管理 Memory(内存)资源,以便让各个进程可以安全地共享机器的内存资源。
另外,内存管理会提供虚拟内存的机制,该机制可以让进程使用多于系统可用Memory的内存,不用的内存会通过文件系统保存在外部非易失存储器中,需要使用的时候,再取回到内存中。
VFS(Virtual File System):
虚拟文件系统。
Linux内核将不同功能的外部设备,例如 Disk 设备(硬盘、磁盘、NAND Flash、Nor Flash 等)、输入输出设备、显示设备等等,抽象为可以通过统一的文件操作接口(open、close、read、write 等)来访问。
这就是 Linux 系统“一切皆是文件”的体现(其实Linux做的并不彻底,因为 CPU、内存、网络等还不是文件,如果真的需要一切皆是文件,还得看贝尔实验室正在开发的"Plan 9”的)。
Network:
网络子系统。
负责管理系统的网络设备,并实现多种多样的网络标准。
IPC(Inter-Process Communication):
进程间通信。
IPC 不管理任何的硬件,它主要负责 Linux 系统中进程之间的通信。
3.2 进程调度(Process Scheduler)
进程调度是 Linux 内核中最重要的子系统,它主要提供对 CPU 的访问控制。因为在计算机中,CPU 资源是有限的,而众多的应用程序都要使用 CPU 资源,所以需要“进程调度子系统”对 CPU 进行调度管理。
进程调度子系统包括4个子模块(见下图),它们的功能如下:
Scheduling Policy:
实现进程调度的策略,它决定哪个(或哪几个)进程将拥有CPU。
Architecture-specific Schedulers:
体系结构相关的部分,用于将对不同CPU的控制,抽象为统一的接口。
这些控制主要在suspend和resume进程时使用,牵涉到CPU的寄存器访问、汇编指令操作等。
Architecture-independent Scheduler:
体系结构无关的部分。
它会和“Scheduling Policy模块”沟通,决定接下来要执行哪个进程,然后通过“Architecture-specific Schedulers模块”resume指定的进程。
System Call Interface:
系统调用接口。
进程调度子系统通过系统调用接口,将需要提供给用户空间的接口开放出去,同时屏蔽掉不需要用户空间程序关心的细节。
3.3 内存管理(Memory Manager, MM)
内存管理同样是 Linux 内核中最重要的子系统,它主要提供对内存资源的访问控制。Linux 系统会在硬件物理内存和进程所使用的内存(称作虚拟内存)之间建立一种映射关系,这种映射是以进程为单位,因而不同的进程可以使用相同的虚拟内存,而这些相同的虚拟内存,可以映射到不同的物理内存上。
内存管理子系统包括 3 个子模块(见下图),它们的功能如下:
Architecture Specific Managers:
体系结构相关部分。
提供用于访问硬件Memory的虚拟接口。
Architecture Independent Manager:
体系结构无关部分。
提供所有的内存管理机制,包括:
以进程为单位的memory mapping;
虚拟内存的Swapping。
System Call Interface:
系统调用接口。
通过该接口,向用户空间程序应用程序提供内存的分配、释放,文件的map等功能。
3.4 虚拟文件系统(Virtual Filesystem, VFS)
传统意义上的文件系统,是一种存储和组织计算机数据的方法。它用易懂、人性化的方法(文件和目录结构),抽象计算机磁盘、硬盘等设备上冰冷的数据块,从而使对它们的查找和访问变得容易。因而文件系统的实质,就是“存储和组织数据的方法”,文件系统的表现形式,就是“从某个设备中读取数据和向某个设备写入数据”。
随着计算机技术的进步,存储和组织数据的方法也是在不断进步的,从而导致有多种类型的文件系统,例如 FAT、FAT32、NTFS、EXT2、EXT3 等等。而为了兼容,操作系统或者内核,要以相同的表现形式,同时支持多种类型的文件系统,这就延伸出了虚拟文件系统(VFS)的概念。VFS 的功能就是管理各种各样的文件系统,屏蔽它们的差异,以统一的方式,为用户程序提供访问文件的接口。
我们可以从磁盘、硬盘、NAND Flash 等设备中读取或写入数据,因而最初的文件系统都是构建在这些设备之上的。这个概念也可以推广到其它的硬件设备,例如内存、显示器(LCD)、键盘、串口等等。我们对硬件设备的访问控制,也可以归纳为读取或者写入数据,因而可以用统一的文件操作接口访问。Linux 内核就是这样做的,除了传统的磁盘文件系统之外,它还抽象出了设备文件系统、内存文件系统等等。这些逻辑,都是由 VFS 子系统实现。
VFS 子系统包括 6 个子模块(见下图),它们的功能如下:
Device Drivers:
设备驱动,用于控制所有的外部设备及控制器。
由于存在大量不能相互兼容的硬件设备(特别是嵌入式产品),所以也有非常多的设备驱动。
因此,Linux内核中将近一半的Source Code都是设备驱动,大多数的Linux底层工程师(特别是国内的企业)都是在编写或者维护设备驱动,而无暇估计其它内容(它们恰恰是Linux内核的精髓所在)。
Device Independent Interface:
该模块定义了描述硬件设备的统一方式(统一设备模型),所有的设备驱动都遵守这个定义,可以降低开发的难度。
同时可以用一致的形势向上提供接口。
Logical Systems:
每一种文件系统,都会对应一个Logical System(逻辑文件系统),它会实现具体的文件系统逻辑。
System Independent Interface:
该模块负责以统一的接口(快设备和字符设备)表示硬件设备和逻辑文件系统,这样上层软件就不再关心具体的硬件形态了。
System Call Interface:
系统调用接口,向用户空间提供访问文件系统和硬件设备的统一的接口。
3.5 网络子系统(Net)
网络子系统在Linux内核中主要负责管理各种网络设备,并实现各种网络协议栈,最终实现通过网络连接其它系统的功能。在Linux内核中,网络子系统几乎是自成体系,它包括5个子模块(见下图),它们的功能如下:
Network Device Drivers:
网络设备的驱动,和VFS子系统中的设备驱动是一样的。
Device Independent Interface:
和VFS子系统中的是一样的。
Network Protocols:
实现各种网络传输协议,例如IP, TCP, UDP等等。
Protocol Independent Interface:
屏蔽不同的硬件设备和网络协议,以相同的格式提供接口(socket)。
System Call interface:
系统调用接口,向用户空间提供访问网络设备的统一的接口。
至于 IPC 子系统,由于功能比较单纯,这里就不再描述。
四、Linux 内核源代码的目录结构
Linux 内核源代码包括三个主要部分:
内核核心代码,包括第 3 章所描述的各个子系统和子模块,以及其它的支撑子系统,例如电源管理、Linux 初始化等;
其它非核心代码,例如库文件(因为 Linux 内核是一个自包含的内核,即内核不依赖其它的任何软件,自己就可以编译通过)、固件集合、KVM(虚拟机技术)等;
编译脚本、配置文件、帮助文档、版权说明等辅助性文件;
以下为内核源代码的顶层目录结构,具体描述如下:
## 内核头文件,需要提供给外部模块(例如用户空间代码)使用
include
## Linux 内核的核心代码,包含了(3.2小节)所描述的进程调度子系统,以及和进程调度相关的模块
kernel
## 内存管理子系统(3.3小节)
mm
## VFS 子系统(3.4小节)
fs
## 不包括网络设备驱动的网络子系统(3.5小节)
net
## IPC(进程间通信)子系统
ipc
## 体系结构相关的代码,例如 arm, x86 等等
arch
## 体系结构相关的头文件,例如 x86
arch/x86/include/asm
## 设备树(Device Tree)文件,例如 arm
arch/arm/boot/dts
## Linux系统启动初始化相关的代码
init
## 提供块设备的层次
block
## 音频相关的驱动及子系统,可以看作“音频子系统”
sound
## 设备驱动(在 Linux kernel 3.10 中,设备驱动占了 49.4 的代码量)
drivers
## 实现需要在内核中使用的库函数,例如 CRC、FIFO、list、MD5 等
lib
## 加密、解密相关的库函数
crypto
## 提供安全特性(SELinux)
security
## 提供虚拟机技术(KVM等)的支持
virt
## 用于生成 initramfs 的代码
usr
## 保存用于驱动第三方设备的固件
firmware
## 一些示例代码
samples
## 一些常用工具,如性能剖析、自测试等
tools
## 用于内核编译的配置文件、脚本等
Kconfig, Kbuild, Makefile, scripts/
## 版权声明
COPYING
## 维护者名单
MAINTAINERS
## Linux 主要的贡献者名单
CREDITS
## Bug 上报的指南
REPORTING-BUGS
## 帮助、说明文档
Documentation, README
原文链接:https://zhuanlan.zhihu.com/p/474337723
赠送书籍:《图解Linux内核(基于6.x)》
🔥🔥🔥 公众号赠书规则:
1、关注下方公众号:Lucifer三思而后行
2、参与方式:转发本文至朋友圈、在看、留言,根据精彩留言点赞数,前 3 位各送 1 本
3、扫码进群,及时获取最新福利活动,广告😡禁入
注意事项:本活动纯属粉丝福利,先到先得。如发现机器或者非真实流量刷赞,发现后将进入黑名单,取消获赠资格。