第11章Linux内核源代码
本章讲述在Linux内核源码中,应该从何处开始查找特定的内核函数。
本书并不要求读者具有C语言编程能力,也不要求读者有一份可参阅的Linux内核源码,
事实上,通过查看内核源码可以在一定深度上理解Linux操作系统,同时这也是一个很好的实
践机会。本章给出了对内核源码的概览:它们是如何编排的以及从何处开始查找特定代码。
11.1怎样得到Linux内核源码
所有主要的Linux系统(Craftworks、Debian、Slackware、RedHat等等)都包含有内核源码,
通常所安装的Linux系统都是通过这些源码创建的。由于Linux总是不断更新,因此用户所安
装的Linux可能已过时,不过从附录A所列的站点上可得到最新的源码,所有这些站点地址都
可在ftp://ftp.cs.helsinki.fi上查到。
Linux内核源码的版本号表示方法非常简单:所有偶数版(如2.0.30)都是已发行的稳定版;
所有奇数版(如2.1.42)都是测试版,本书是基于2.0.30版撰写的。测试版包含所有的新特征,
并支持所有的新设备,虽然测试版并不稳定,并且可能提供了一些用户不想要的东西,但对
于Linux与用户沟通而言,测试新的内核是很重要的。不过请注意,在尝试非产品型的测试版
之前,最好先完全备份系统。
对内核源码的修改是作为patch文件出现的,patch工具提供了一组对源码文件的编辑。例
如,若想把2.0.29源码升级为2.0.30版,则要使用patch文件来完成对源码的编辑,操作如下:
这样做可以避免对所有源码文件的拷贝。在http://www.linuxhq.com站点上可找到很好的
内核源码的patch。
11.2内核源码的编排
在源码目录树的最顶端(/usr/src/linux)可看到如下一些目录:
*archarch子目录包含所有的特定体系结构的内核源码,它的子目录分别对应着一种
Linux所支持的体系结构,例如i386和alpha。
*includeinclude子目录包含大部分的编译内核源码所需文件。
*init此目录下包含了内核的初始化代码,由此可以很好地开始了解内核是如何工作的。
*mm此目录下包含了所有内存管理代码,特定体系结构的内存管理代码在arch/*/mm目
录下。
*drivers此目录下包含了系统所有的设备驱动程序,其下子目录各针对不同的设备驱动
程序类。
*ipc此目录下包含了内核的内部进程通信代码。
*modules此目录只是用来保存创建的模块。
*fs所有文件系统代码,其下子目录各针对不同的系统所支持的文件系统。
*kernel内核主代码,特定体系结构内核代码保存在arch/*/kernel中。
*net内核的网络代码。
*lib此目录包含内核库代码,特定体系结构的库代码保存在arch/*/lib目录下。
*scripts此目录包含了内核设置时用到的脚本。
11.3从何处看起
像Linux这样复杂的大程序,探究起来使人迷茫,这就像一个找不出头绪的大线团。要查
看内核的某一部分通常会被引向许多其他的相关文件,最后甚至忘记了最初的动机。下面给
出了一些提示,根据这些提示,对于给定的内容即可找到最好的开始阅读代码部分。
1.系统启动和初始化
在基于Intel的系统中,通常先运行loadlin.exe或LILO,由这两个程序将内核载入内存并启
动内核,之后便由内核控制系统。在arch/i386/kernel/head.s中可找到这一部分,head.s先进行
一些特定体系结构的安装,然后跳转到init/main.c中的main()例程。
2.内存管理
有关内存管理的代码大部分都在mm中,但与特定体系结构相关的部分则保存在
arch/*/mm中,内存缺页处理代码在mm/memory.c中,内存映射和页缓冲代码在mm/filemap.c
中,实现缓冲区缓存部分代码在mm/buffer.c中,页交换代码在mm/swap_state.c和
mm/swapfile.c中。
3.内核
大部分通用内核代码在kernel中,与特定体系结构相关的代码在arch/*/kernel中,调度进
程代码在kernel/sched.c中,创建子进程代码在kernel/fork.c中,BottomHalf控制程序代码在
include/linux/interrupt.h中,task_struct数据结构的定义在include/linux/sched.h中。
4.PCI
PCI伪驱动程序在drivers/pci/pci.c中,系统全局定义在include/linux/pci.h中。每种体系结
构都有其特定的PCIBIOS代码,如AlphaAxp的代码在arch/alpha/kernel/bios32.c中。
5.内部进程间通信
所有相关代码都在ipc中,所有的SystemVIPC对象都有一个ipc_perm数据结构,在
include/linux/ipc.h中有该数据结构的定义。SystemV的消息机制代码在ipc/msg.c中,共享内
存代码在ipc/shm.c中,信号量代码在ipc/sem.c中,管道代码在ipc/pipe.c中。
6.中断处理
内核的中断处理代码几乎都与特定微处理器相关。Intel的中断处理代码在
arch/i386/kernel/irq.c中,并且定义在include/asm-i386/irq.h中。
7.设备驱动程序
大部分的Linux内核源码行在设备驱动程序中,所有设备驱动程序代码在drivers中,并分
为如下几类:
*/block块设备驱动程序(如ide.c)。若要了解其初始化过程,参看drivers/block/genhd.c中
的device_setup()函数,该函数不仅能初始化硬盘,也可以初始化网络。块设备包括IDE
和SCSI设备。
*/char字符设备驱动程序,例如ttys、串口和鼠标。
*/cdromLinux的所有CDROM代码。在此可找到特定的CDROM设备(如SoundblasterCD
ROM),请注意,ideCD驱动程序在drivers/block下的ide-cd.c中,而SCSICD驱动程序在
drivers/scsi中的scsi.c中。
*/pciPCI伪驱动程序代码,由此可了解PCI子系统是如何映射和初始化的,arch/alpha
/kernel/bios32.c中的AlphaPCI固化代码也值得一看。
*/scsi所有的SCSI代码,以及Linux所支持的所有scsi设备驱动程序代码。
*/net所有网络设备驱动程序代码。
*/sound所有声卡驱动程序代码。
8.文件系统
EXT2文件系统的代码都在fs/ext2/目录下,其数据结构定义在include/linux/ex2_fs.h、
ext2_fs_i.h和ext2_fs_sb.h中,虚文件系统(VirtualFileSystem)数据结构在include/linux/fs.h中,
代码在fs/*中,缓冲区缓存代码在fs/buffer.c中。
9.网络
网络部分代码在net中,其大部分的include文件在include/net中,BSD套接字代码在
net/socket.c中,IP版本4INET套接字代码在net/ipv4/af_inet.c中,常用的协议支持代码(包括
sk_buff控制例程)在net/core中,TCP/IP网络代码在net/ipv4中,而网络设备驱动程序在
drivers/net中。
10.模块
内核模块代码一部分在kernel中,另一部分在模块包中,内核代码都在kernel/mcdules.c中,
其数据结构和内核守护程序kerneld消息分别在include/linux/module.h和include/linux/kerneld.h
中,ELF对象文件的结构定义在include/linux/elf.h中。