1.序言
本文是“Linux内核剖析”系列文章的第一篇linux教程,会以内核的核心功能为出发点,描述Linux内核的整体构架,以及构架之下主要的软件子系统。以后,会介绍Linux内核源文件的目录结构,并和各个软件子系统对应。
注:本文和其它的“Linux内核剖析”文章都基于如下约定:
a)内核版本为Linux3.10.29(该版本是一个longterm的版本,会被Linux社区持续维护起码2年),可以从下边的链接获取:
b)鉴于嵌入式系统大多使用ARM处理器,因而涉及到体系结构部份的内容,都以ARM为剖析对象
2.Linux内核的核心功能
如右图所示,Linux内核只是Linux操作系统一部份。对下,它管理系统的所有硬件设备;对上,它通过系统调用,向LibraryRoutine(比如C库)或则其它应用程序提供插口。
因而,其核心功能就是:管理硬件设备,供应用程序使用。而现代计算机(无论是PC还是嵌入式系统)的标准组成,就是CPU、Memory(显存和外存)、输入输出设备、网络设备和其它的外围设备。所以为了管理这种设备,Linux内核提出了如下的构架。
3.Linux内核的整体构架3.1整体构架和子系统界定
上图说明了Linux内核的整体构架。按照内核的核心功能,Linux内核提出了5个子系统,分别负责如下的功能:
1.ProcessScheduler,也叫做进程管理、进程调度。负责管理CPU资源,便于让各个进程可以以尽量公正的方法访问CPU。
2.MemoryManager,显存管理。负责管理Memory(显存)资源,便于让各个进程可以安全地共享机器的显存资源。另外,显存管理会提供虚拟显存的机制,该机制可以让进程使用少于系统可用Memory的显存,不用的显存会通过文件系统保存在外部非易失储存器中,须要使用的时侯,再取回到显存中。
3.VFS(VirtualFileSystem),虚拟文件系统。Linux内核将不同功能的外部设备,比如Disk设备(硬碟、磁盘、NANDFlash、NorFlash等)、输入输出设备、显示设备等等,具象为可以通过统一的文件操作插口(open、close、read、write等)来访问。这就是Linux系统“一切皆是文件”的彰显(虽然Linux做的并不彻底,由于CPU、内存、网络等还不是文件,假如真的须要一切皆是文件,还得看贝尔实验室正在开发的"Plan9”的)。
4.Network,网路子系统。负责管理系统的网路设备,并实现多种多样的网路标准。
5.IPC(Inter-ProcessCommunication),进程间通讯。IPC不管理任何的硬件,它主要负责Linux系统中进程之间的通讯。
3.2进程调度(ProcessScheduler)
进程调度是Linux内核中最重要的子系统,它主要提供对CPU的访问控制。由于在计算机中,CPU资源是有限的,而诸多的应用程序都要使用CPU资源,所以须要“进程调度子系统”对CPU进行调度管理。
进程调度子系统包括4个子模块(见右图),它们的功能如下:
1.SchedulingPolicy,实现进程调度的策略,它决定那个(或哪几个)进程将拥有CPU。
2.Architecture-specificSchedulers,体系结构相关的部份,用于将对不同CPU的控制,具象为统一的插口。这种控制主要在suspend和resume进程时使用,牵连到CPU的寄存器访问、汇编指令操作等。
3.Architecture-independentScheduler,体系结构无关的部份。它会和“SchedulingPolicy模块”沟通,决定接出来要执行那个进程,之后通过“Architecture-specificSchedulers模块”resume指定的进程。
4.SystemCallInterface,系统调用插口。进程调度子系统通过系统调用插口,将须要提供给用户空间的插口开放出去,同时屏蔽掉不须要用户空间程序关心的细节。
3.3显存管理(MemoryManager,MM)
显存管理同样是Linux内核中最重要的子系统,它主要提供对显存资源的访问控制。Linux系统会在硬件化学显存和进程所使用的显存(也称虚拟显存)之间构建一种映射关系,这些映射是以进程为单位,因此不同的进程可以使用相同的虚拟显存,而这种相同的虚拟显存,可以映射到不同的化学显存上。
显存管理子系统包括3个子模块(见右图),它们的功能如下:
1.ArchitectureSpecificManagers,体系结构相关部份。提供用于访问硬件Memory的虚拟插口。
2.ArchitectureIndependentManager,体系结构无关部份。提供所有的显存管理机制linux 内核之 分析有源代码,包括:以进程为单位的memorymapping;虚拟显存的Swapping。
3.SystemCallInterface,系统调用插口。通过该插口,向用户空间程序应用程序提供显存的分配、释放,文件的map等功能。
3.4虚拟文件系统(VirtualFilesystem,VFS)
传统意义上的文件系统,是一种储存和组织计算机数据的方式。它用易懂、人性化的方式(文件和目录结构),具象计算机c盘、硬盘等设备上冰凉的数据块linux 内核之 分析有源代码,进而使对它们的查找和访问显得容易。因此文件系统的实质,就是“存储和组织数据的方式”,文件系统的表现方式,就是“从某个设备中读取数据和向某个设备写入数据”。
随着计算机技术的进步,储存和组织数据的方式也是在不断进步的,因而造成有多种类型的文件系统,比如FAT、FAT32、NTFS、EXT2、EXT3等等。而为了兼容,操作系统或则内核,要以相同的表现方式,同时支持多种类型的文件系统,这就延展出了虚拟文件系统(VFS)的概念。VFS的功能就是管理各类各样的文件系统,屏蔽它们的差别,以统一的方法,为用户程序提供访问文件的插口。
我们可以从c盘、硬盘、NANDFlash等设备中读取或写入数据,因此最初的文件系统都是建立在这种设备之上的。这个概念也可以推广到其它的硬件设备,比如显存、显示器(LCD)、键盘、串口等等。我们对硬件设备的访问控制,也可以归纳为读取或则写入数据,因此可以用统一的文件操作插口访问。Linux内核就是这样做的,不仅传统的c盘文件系统之外,它还具象出了设备文件系统、内存文件系统等等。这种逻辑,都是由VFS子系统实现。
VFS子系统包括6个子模块(见右图),它们的功能如下:
1.DeviceDrivers,设备驱动,用于控制所有的外部设备及控制器。因为存在大量不能互相兼容的硬件设备(非常是嵌入式产品),所以也有特别多的设备驱动。因而,Linux内核中将近一半的SourceCode都是设备驱动,大多数的Linux底层工程师(非常是国外的企业)都是在编撰或则维护设备驱动,而无瑕恐怕其它内容(它们恰恰是Linux内核的真谛所在)。
2.DeviceIndependentInterface,该模块定义了描述硬件设备的统一形式(统一设备模型),所有的设备驱动都遵循这个定义,可以减少开发的难度。同时可以用一致的形势向下提供插口。
3.LogicalSystems,每一种文件系统,就会对应一个LogicalSystem(逻辑文件系统),它会实现具体的文件系统逻辑。
4.SystemIndependentInterface,该模块负责以统一的插口(快设备和字符设备)表示硬件设备和逻辑文件系统,这样下层软件就不再关心具体的硬件形态了。
5.SystemCallInterface,系统调用插口,向用户空间提供访问文件系统和硬件设备的统一的插口。
3.5网路子系统(Net)
网路子系统在Linux内核中主要负责管理各类网路设备,并实现各类网路合同栈,最终实现通过网路联接其它系统的功能。在Linux内核中,网路子系统几乎是自成体系,它包括5个子模块(见右图),它们的功能如下:
1.NetworkDeviceDrivers,网路设备的驱动,和VFS子系统中的设备驱动是一样的。
2.DeviceIndependentInterface,和VFS子系统中的是一样的。
3.NetworkProtocols,实现各类网路传输合同,比如IP,TCP,UDP等等。
4.ProtocolIndependentInterface,屏蔽不同的硬件设备和网路合同,以相同的格式提供插口(socket)。
5.SystemCallinterface,系统调用插口红旗linux,向用户空间提供访问网路设备的统一的插口。
至于IPC子系统,因为功能比较单纯,这儿就不再描述了。
4.Linux内核源代码的目录结构
Linux内核源代码包括三个主要部份:
1.内核核心代码,包括第3章所描述的各个子系统和子模块,以及其它的支撑子系统,比如电源管理、Linux初始化等
2.其它非核心代码,比如库文件(由于Linux内核是一个自包含的内核,即内核不依赖其它的任何软件,自己就可以编译通过)、固件集合、KVM(虚拟机技术)等
3.编译脚本、配置文件、帮助文档、版权说明等辅助性文件
右图示使用ls命令见到的内核源代码的顶楼目录结构,具体描述如下。
include/----内核头文件,须要提供给外部模块(比如用户空间代码)使用。
kernel/----Linux内核的核心代码,包含了3.2小节所描述的进程调度子系统,以及和进程调度相关的模块。
mm/----显存管理子系统(3.3小节)。
fs/----VFS子系统(3.4小节)。
net/----不包括网路设备驱动的网路子系统(3.5小节)。
ipc/----IPC(进程间通讯)子系统。
arch//----体系结构相关的代码,譬如arm,x86等等。
arch//mach-----具体的machine/board相关的代码。
arch//include/asm----体系结构相关的头文件。
arch//boot/dts----设备树(DeviceTree)文件。
init/----Linux系统启动初始化相关的代码。
block/----提供块设备的层次。
sound/----音频相关的驱动及子系统,可以看作“音频子系统”。
drivers/----设备驱动(在Linuxkernel3.10中,设备驱动占了49.4的代码量)。
lib/----实现须要在内核中使用的库函数,比如CRC、FIFO、list、MD5等。
crypto/-----加密、解密相关的库函数。
security/----提供安全特点(SELinux)。
virt/----提供虚拟机技术(KVM等)的支持。
usr/----用于生成initramfs的代码。
firmware/----保存用于驱动第三方设备的固件。
samples/----一些示例代码。
tools/----一些常用工具,如性能分析、自测试等。
Kconfig,Kbuild,Makefile,scripts/----用于内核编译的配置文件、脚本等。