前面博文中,算是把个人认为关于 Linux 内核学习必需的“预备知识”写完了,接下来就是对内核源码的学习。在源码学习之前,我们先来看看 Linux 0.11 内核的一个概况,以便于后续学习有个大纲,不致走偏。
对于那些已经在“预备知识”中阐述过的知识点在这里就不再重复;而对于那些会在后续博文详细描述的(如进程)也暂不述及。
本文主要参考自《Linux 内核完全注释》和《Linux 内核设计的艺术》两书。
内核运行环境假定
在接下来得内核源码分析中,跟《Linux 内核设计的艺术》一书一致,我们假定 Linux 0.11 内核运行在如下的工作环境中:
计算机是基于 IA(Intel Architecture)-32 系列 CPU,安装了单色显示器、标准键盘、一个软驱、一块硬盘、16 MB 内存,在内存中开辟了 2MB 内存作为虚拟盘,并在 BIOS 中设置软驱为启动设备。
Linux 内核模式和体系结构
一个完整可用的操作系统主要由 4 部分组成:硬件、操作系统内核程序、操作系统服务程序和用户应用程序,如下图所示。用户应用程序是指那些由用户自行编写的各种应用程序;操作系统服务程序是指那些向用户提供服务并被看作是操作系统部分功能的程序,如 shell 命令解释系统;操作系统内核程序则是对硬件资源的抽象和访问调度。
Linux 内核模式
Linux 0.11 内核采用了整体式的单内核模式
(另一模式是层次式的微内核模式)。在《Understanding the Linux Kenel》(第 3 版)一书对此有一简单的描述:
It (
Monolithic kernel
) is a large, complex do-it-yourself program, composed of several logically different components. In this, it is quite conventional; most commercial Unix variants are monolithic. (Notable exceptions are the Apple Mac OS X and the GNU Hurd operating systems, both derived from the Carnegie-Mellon’s Mach, which follow amicrokernel
approach.)
单内核模式的主要优点是内核代码结构紧凑、执行速度块,不足之处在于层次结构性不强。
在单内核模式的系统中,操作系统所提供的服务的流程为:应用程序使用指定的参数值执行系统调用指令(int 0x80),使 CPU 从用户态切换到内核态,然后操作系统根据具体的参数值调用特定的系统调用服务程序,而这些服务程序则根据需要再调用底层的一些支持函数以完成特定的功能。在完成了应用程序所要求的服务后,操作系统又使 CPU 从内核态切换回用户态,从而返回到应用程序中继续执行后面的指令。
因此概要地讲,单内核模式的内核也可粗略地分为三个层次:调用服务的主程序层、执行系统调用的服务层和支持系统调用的底层函数。如下图所示:
Linux 体系结构
Linux 内核主要由 5 个模块组成:进程调度模块、内存管理模块、文件系统模块、进程间通信模块和网络接口模块:
进程调度模块
负责控制进程对 CPU 资源的使用。所采取的调度策略是各进程能够公平合理地访问 CPU,同时保证内核能够及时地执行硬件操作。内存管理模块
用于确保所用进程能够安全地共享机器主内存区。同时,内存管理模块还支持虚拟内存管理方式,使得 Linux 支持进程使用比实际内存空间更多的内存容量;并可以利用文件系统把暂时不用的内存数据交换到外部存储设备上去,当需要时再交换回来。文件系统模块
用于支持对外部设备的驱动和存储。虚拟文件系统
(Virtual File System)通过向所有的外部存储设备提供一个通用的文件接口,隐藏了各种硬件设备的不同细节,从而提供并支持与其他操作系统兼容的多种文件系统格式。进程间通信模块
用于支持多种进程间的信息交换方式。网络接口模块
提供多种网络通信标准的访问并支持许多网络硬件。
这几个模块的依赖关系如下图所示(其中的连线表示它们之间的依赖关系,虚线和虚框部分表示 Linux 0.11 中还未实现的部分):
另外,根据 Linux 0.11 内核源码可将内核主要模块及它们之间关系绘制如下:
Linux 内核对内存的使用方法
在 Linux 0.11 内核中,为了有效地使用物理内存,内存被划分成几个功能区域,如下图所示:
其中,Linux 内核程序占据在物理内存的开始部分,接下来是供硬盘或软盘等块设备使用的高速缓冲区部分(其中还要扣除显卡内存和 ROM BIOS 所占用的内存地址范围 640K~1MB)。当一个进程需要读取块设备中的数据时,系统会首先把数据读到高速缓冲区中;当有数据需要写到块设备上时,系统也先将数据放到高速缓冲区中,然后由块设备驱动程序将数据写到相应的设备上。内存的最后部分是供所有程序申请和使用的主内存区。内核程序在使用主内存区时,也同样首先要向内存管理模块提出申请,并在申请成功后方能使用。对于含有 RAM 虚拟盘的系统,主内存区头部还要划去一部分,共虚拟盘存放数据。
另外,Linux 0.11 内核中人工定义系统支持的最大任务数位 64,每个进程空间的虚拟地址空间是 64MB,并且每个进程的虚拟地址起始位置是”任务号*64MB”。因此所有进程所使用的虚拟地址空间是 64MB*64=4GB,如下图所示:
Linux 内核源码目录结构
Linux 0.11 内核源码(linux-0.11.tar.gz)目录如下:
通过编译链接,可以生成内核映像文件,如下图所示:
关于各目录详细信息请参考《Linux 内核完全注释》一书。