20170805 --iRonMan
Linux内核是一种单内核模式的系统,因此,内核中所有的程序几乎都紧密的联系在一起。由于他们之间的依赖和调用关系非常的紧密,所以在阅读一个源代码文件是往往要顺带参阅一下跟它有关系的文件。
因此,我们有必要先了解一下源代码文件的目录结构,搞清楚它们的家谱。
文中的内核版本是Linux2.6.35.7
图:linux源代码目录结构示意图
(一) scripts目录:
该目录中不包含任何核心代码,该目录下存放了用来配置内核的脚本和应用程序源码。
(二) Lib目录:
该目录主要分两部分:gnuzip加压缩算法,用于在系统启动过程中将压缩的内核镜像解压缩;
剩余的文件用于实现一个C库的子集,主要包括字符串和内存操作等相关函数。
(三) Mm目录:
该目录主要包含了和体系结构无关的内存管理代码,包括通用的分页模型的框架、伙伴算法的实现和对象缓冲器slab的实现代码。这些代码最终依赖具体的平台完成相关操作。
(四) Include目录:
这 个目录包含linux源代码目录树中绝大部分头文件,每个体系架构都在该目录下对应一个子目录,该子目录中包含了给定体系结构所必需的宏定义和内联函数。 这些内联函数很多都是适用汇编语言实现的,而且在编译内核的过程中,首先会建立一个名称为include/asm的符号链接,该链接指向目标体系结构在该 目录中的子目录,使得与体系结构无关内核代码可以使用如下简洁的形式来引用语体系结构相关的代码为:
#include “Linux/asm/xxx.h”
除 了与体系结构相关的头文件之外,该目录还用与存放于体系架构无关的内核模块的头文件,这些头文件都是某一个内核模块对外提供的接口,供内核其他模块使用。 这些接口主要包含进程管理访问接口、内存管理访问接口、文件操作访问接口、网络访问接口等,这些接口函数通常用于内核模块的编写,如编写设备驱动程序或者 设计一个新的文件系统等。
(五) Init目录:
该目录中存放的是系统核心初始化代码,内核初始化入口函数 start_kernel就是在该目录下的文件main.c内实现的。内核初始化入口函数start_kernel负责调用其它模块的初始化函数,完成系 统的初始化工作。该目录种存放的代码还负责测试CPU性能,算出系统处理器的BogoMIPS值[w1] ,该值代表了处理器在一定时间执行循环操作的次数。除此之外,该目录还负责完成根文件系统初始化过程中的相关工作。
(六) Kernel目录:
该 目录存放的是linux内核的最核心代码,用于实现系统的核心模块,这些模块包括进程管理、进程调度器、中断处理、系统时钟管理、同步机制等。该目录中的 代码实现了这些核心模块的主体框架,独立于具体的平台和系统架构。核心模块与平台相关代码存放在目录arch中,具体看后面对该目录的介绍。
(七) Arch目录:
该目录中每个子目录都与某种体系结构对应,用于存放系统结构相关代码,向平台无关的系统核心模块提供所需的功能接口。每个体系结构对应的子目录下通常至少包含以下几个子目录:
* Kernel子目录:用于存放特定体系结构特有信号量的实现代码和对称多处理器(Symmetric MultiProccessing,简称SMP)相关模块。
* Lib子目录:用于存放以来依赖当前体系结构的辅助功能,如利用当前体系结构特性实现的strlen和memcpy内存操作函数;与通用的实现方法相比,他们的开销小、更加高效。
* Mm子目录:用于存放体系架构特定的内存管理模块,包括内存的初始化、页表管理等内容。
* Boot子目录:该目录中包含了当前平台上系统引导过程使用的部分或全部代码。这部分代码以来当前平台,用于完成向系统内存装载内核镜像的工作。
浏览内核代码之前,有必要知道内核源码的整体分布情况,按照惯例,内核代码安装在/usr/src/linux目录下,该目录下的每一个子目录都代表了一个特定的内核功能性子集,下面针对2.6.23版本进行简单描述。
1)Documentation
这个目录下面没有内核代码,只有很多质量参差不齐的文档,但往往能够给我们提供很多的帮助。
2)Arch
所有与体系结构相关的代码都在这个目录以及include/asm-*/目录中,Linux支持的每种体系结构在arch目录下都有对应的子目录,而在每个体系结构特有的子目录下又至少包含3个子目录。
kernel:存放支持体系结构特有的诸如信号量处理和SMP之类特征的实现。
lib:存放体系结构特有的对诸如strlen和memcpy之类的通用函数的实现。
mm:存放体系结构特有的内存管理程序的实现。
除了这3个子目录之外,大多数体系结构在必要的情况下还有一个boot子目录,包含了在这种硬件平台上启动内核所使用的部分或全部平台特有代码。
此外,大部分体系结构所特有的子目录还根据需要包含了供附加特性使用的其他子目录。比如,i386目录包含一个math-emu子目录,其中包括了在缺少数学协处理器(FPU)的CPU上运行模拟FPU的代码。
3)drivers
这个目录是内核中最庞大的一个目录,显卡、网卡、SCSI适配器、PCI总线、USB总线和其他任何Linux支持的外围设备或总线的驱动程序都可以在这里找到。
4)fs
虚拟文件系统(VFS,Virtual File System)的代码,和各个不同文件系统的代码都在这个目录中。Linux支持的所有文件系统在fs目录下面都有一个对应的子目录。比如ext2文件系统对应的是fs/ext2目录。
一个文件系统是存储设备和需要访问存储设备的进程之间的媒介。存储设备可能是本地的物理上可访问的,比如硬盘或CD-ROM驱动器,它们分别使用ext2/ext3和isofs文件系统;也可能是通过网络访问的,使用NFS文件系统。
还有一些虚拟文件系统,比如proc,它以一个标准文件系统出现,然而,它其中的文件只存在于内存中,并不占用磁盘空间。
5)include
这个目录包含了内核中大部分的头文件,它们按照下面的子目录进行分组。
include/asm-*/,这样的子目录有多个,每一个都对应着一个arch的子目录,比如include/asm-alpha、include/asm-arm、include/asm-i386等。每个子目录中的文件都定义了支持给定体系结构所必须的预处理器宏和内联函数,这些内联函数多数都是全部或部分使用汇编语言实现的。
编译内核时,系统会建立一个从include/asm目录到目标体系结构特有的目录的符号链接。比如对于arm平台,就是include/asm-arm到include/asm的符号链接。因此,体系结构无关部分的内核代码可以使用如下形式包含体系相关部分的头文件。
#include <asm/some-file>
include/linux/,与平台无关的头文件都在这个目录下面,它通常会被链接到目录/usr/include/linux(或者它里面的所有文件会被复制到/usr/include/linux目录下面)。因此用户应用程序里和内核代码里的语句:
#include <linux/some-file>
包含的头文件的内容是一致的。
include目录下的其他子目录,在此不做赘述。
6)init
内核的初始化代码。包括main.c、创建早期用户空间的代码以及其他初始化代码。
7)ipc
IPC,即进程间通信(interprocess communication)。它包含了共享内存、信号量以及其他形式IPC的代码。
8)kernel
内核中最核心的部分,包括进程的调度(kernel/sched.c),以及进程的创建和撤销(kernel/fork.c和kernel/exit.c)等,和平台相关的另外一部分核心的代码在arch/*/kernel目录。
9)lib
库代码,实现了一个标准C库的通用子集,包括字符串和内存操作的函数(strlen、mmcpy和其他类似的函数)以及有关sprintf和atoi的系列函数。与arch/lib下的代码不同,这里的库代码都是使用C编写的,在内核新的移植版本中可以直接使用。
10)mm
包含了体系结构无关部分的内存管理代码,体系相关的部分位于arch/*/mm目录下。
11)net
网络相关代码,实现了各种常见的网络协议,如TCP/IP、IPX等。
12)scripts
脚本,这个目录下全部是脚本文件,这些脚本文件不是linux内核工作时使用的,而是用来辅助对linux内核进行配置编译生产的。当运行make menuconfig或者make xconfig之类的命令配置内核时,用户就是和位于这个目录下的脚本进行交互的。
13)block
block层的实现。最初block层的代码一部分位于drivers目录,一部分位于fs目录,从2.6.15开始,block层的核心代码被提取出来放在了顶层的block目录。
14)crypto
内核本身所用的加密API,实现了常用的加密和散列算法,还有一些压缩和CRC校验算法。
15)security
这个目录包括了不同的Linux安全模型的代码,比如NSA Security-Enhanced Linux。对计算机免于受到病毒和黑客的侵害很重要.
16)sound
声卡驱动以及其他声音相关的代码,跟音频处理相关。
17)usr
实现了用于打包和压缩的的cpio等。。这个文件夹中的代码在内核编译完成后创建这些文件。
18)virt
此文件夹包含了虚拟化代码,它允许用户一次运行多个操作系统。通过虚拟化,客户机操作系统就像任何其他运行在Linux主机的应用程序一样运行。
根目录下的一些单独文件:
COPYING:许可和授权信息。Linux内核在GPLv2许可证下授权。该许可证授予任何人有权免费
去使用、修改、分发和共享源代码和编译代码。然而,没有人可以出售源代码。
CREDITS : 贡献者列表。
Kbuild:是kernel build的意思,就是内核编译的意思,设置一些内核设定的脚本。打个比方,
这个脚本设定一个ARCH变量,这是开发者想要生成的内核支持的处理器类型。
Kconfig:这个脚本会在开发人员配置内核的时候用到。
MAINTAINERS:这是一个目前维护者列表,他们的电子邮件地址,主页,和他们负责开发和维护的内核的特定部分或文件。
当一个开发者在内核中发现一个问题,并希望能够报告给能够处理这个问题的维护者时,这是是很有用的。
Makefile:这个脚本是编译内核的主要文件。这个文件将编译参数和编译所需的文件和必要的信息传给编译器。
README:这个文档提供给开发者想要知道的如何编译内核的信息。
REPORTING-BUGS:这个文档提供如何报告问题的信息。
总结
这么多目录中比较重要的是arch和drivers目录,然后其他有点相关的还有include、block、mm、net、lib等目录。
根目录下的单文件比较重要的是Kbuild,Kconfig,Makefile。
NOTE:
本文是学习Linux内核注释后的个人笔记,图片摘自网上,学习和分享……