Linux内核源码阅读系列(2)-内核的构成 之 一

“Linux系统”,通常我们都这样叫它。但是,这个说法简便的同时却缺少了一个重要的信息和概念。很多Linux发行版本都有自己特别的名字,但事实上他们都应该有一个共同的名字,那就是“GNU Linux”。这个前缀很重要,它表明了Linux操作系统的构成。一个是Linux内核,另外一个是主要由GNU组织提供的各种基础应用程序。而这个系列的文章里,我的讨论对象仅仅是“Linux内核”。事实上Linux内核几乎就是操作系统,如果再给它添加一个shell用来提供用户操作接口的话。操作系统是提供一个用户概念里的计算机的软件。它最基础的功能是提供用户和计算机硬件之件的抽象——这件事情Linux内核+shell就能够完成。

Linux内核-她的芳名

Linux内核是模仿传统的UNIX内核创建的,整个内核是一个非常大的程序,并非多个程序的组合,所以,Linux内核通常被成为“宏内核”。又因为她的构成方法深受传统的学院派UNIX内核的影响——特别是Minix(注1)——所以,又被称为”Monolothic kernel”。与Linux内核组成方式相对的是GNU Hurd内核,它是GNU组织计划中的尚未长大的婴儿。Hurd中以一个叫做”March”的部件为核心将n个程序组合起来的方式构成内核。以这种方式组成的内核被称为“微内核”。

另一方面,Linux内核采用了模块化的方式组织自身,所有,Linux内核可以通过编译选项方便的进行裁减形成一个体积微小的操作系统内核,某些时候她可能会被叫做“微(小)内核”,总之,这个意义不要搞混阿,这里说的仅仅是她的苗条身段罢了。

微软的Windows操作系统是“微内核”,而由BSD UNIX发展而来的Apple公司的Mac OS则很显然是宏内核。

内核代码-你不可能对她一见钟情

Linux0.0.1的代码不过才6000-8000行,互联网的上的很多说法是说,这个版本的内核代码比较适合初学者阅读。但我的想法却恰恰与此相反,Linux0.0.1代码我记得在大学3年时候曾经翻看过,但是在此以后就没有什么印象了,因为我根本用不着它。反而是工作以后,整天跟Linux2.6内核接触,却一天天的熟悉起来。由此说明,数量的多少并不是决定一个事情难易程度的主要因素,关键看自己努力与否。hoho,大嘴大话。总之,虽然Linux2.6.18内核的代码已经庞大到吓人,但是我还是觉得读这个版本的源代码对实践有真正的意义。虽然整体很大,但是化整为零的方法开始吧。解开她的第一颗钮扣之前,你得先得到她。www.kernel.org提供了一个mirror列表,你可以选择距离你比较近的下载——如果能找到邻家女孩又何必舍近求远呢?如果你在中国国内,直接使用下面的命令就可以了。注意,给wget设置proxy这个事情不在我的博客里。:)

$ wget http://www.cn.kernel.org/pub/linux/kernel/v2.6/linux-2.6.18.8.tar.bz2

解压,并将她放入你自己喜欢的目录比如~/workspace/kernel-src/。掀起盖头看一下吧。大概应该是长这个样子:

adam@capricorn-x61:~/workspace/kernel-src/linux-2.6.18.8$ ls
COPYING        MAINTAINERS     arch     fs       kernel  scripts
CREDITS        Makefile        block    include  lib     security
Documentation  README          crypto   init     mm      sound
Kbuild         REPORTING-BUGS  drivers  ipc      net     usr
kernel Linux内核的动作控制,基本功能
mm 内存管理(物理内存,虚拟内存)
fs 虚拟文件系统(VFS),各个子目录下面是各种文件系统
net 网络协议,各个子目录下面是各种协议
ipc System V的进程间通讯(IPC)机制(共享内存,信号量,消息)
init 各种Linux启动时需要的代码,初始化代码
crypto 加密处理的共通部分
block 块设备的设备控制代码的共通部分
drviers 各种设备的驱动
sound 音频设备的驱动等
arch 各种体系结构相关的代码
include Linux内核在编译的时候需要查看的头文件,开发内核模块后者设备驱动时必须参照的编程接口。其中,各个体系结构相关的代码都是以asm开头

从上面这个表你可以看到各个子目录的大致情况,不至于需要寻找代码时无处下手。除此以外,在内核顶层目录里面你看到的各个文件“自我描述”的文件名,这个就不多说了。值得一提的是Documentation目录。Linux内核采取Bazzar方式开发,开发者的组织比较分散,所以为了保证协同工作的顺利,Linux内核的文档应该说是比较详细的,而且其中不乏幽默和智慧。但Documentation目录下的文档还是准备给用户看的,你可以在里面找到与内核开发相关的很多内容。刚刚开始的话,可以读一读

Documentation/CodingStyle

。另外,最近有一本被翻译成中文版就变很火的书”Dreaming in Code”——中文名《梦断代码》,若你真的有空,并且真的不会对内核代码一见钟情,也可以读一读。另外,若是实在闲的慌可以上这个邮件列表去打嘴炮。你得知道,在中国,空谈和争论是一种破文化,恩。下面有一张她的X光片。我从小在医院长大,而小时候最要好的玩伴的老爸是放射科的大夫,看胸片那是“耳濡目染”,恩。也希望你喜欢。

Linux内核模块以及它们之间的关系

Linux内核模块以及它们之间的关系

这张图片之中,箭头的意义可能是模块之间调用或者关联关系,但是仅仅表示这个意思,并不严格,不要较真。

内核的核-她的骨架

优秀的进程调度(process scheduling)

我说Linux是女人你千万别不信,由她的复杂精巧的程度就可以看出性别来。而且,她有一个非常优秀的多任务处理机制——进程调度——这就更加说明她的性别。

女性的大脑结构决定了她可以一心多用:她可以同时用手玩4—5个球;她可以一边用电脑,一边接电话,同时还听别人在她身后说话,并且在整个过程中又不断地喝咖啡;她可以在谈话中同时涉及好几个毫不相关的话题,变换五种语调来转移话题或强调重点。而男人只能分辨其中的三种语调,所以男人在听女人谈话的时候总是跟不上她的思路。

详细的证明过程可以参照《为什么男人爱撒谎女人爱哭泣》,-_-!!!。还有就是,如果你仔细看过她的启动消息或者日记,那个verbose的喋喋不休会让你抓狂——特别是新手上路的时候,这又是一个证据。

要搞懂她这种古怪的行为,就必须深刻认识到“在CPU数目限制的情况下,她事实上不可能同时执行很多任务,她只能通过调度来实现看上去同时执行多个任务的假象”这一点。关于这个smart girl怎么做到这一点的,后面我想细细道来。这里需要说的是,她这一部分的故事大概都在源代码的kernel目录下。

同样优秀的中断处理(interrupt handling)

中断,顾名思义就是暂时停止某件事情的执行,而后,当然你还是要想办法把它做完。就像我gf下厨房,炒菜的中途发现忘记了买酱油一样,她得先关掉炉火,出去弄瓶酱油回来再继续炒菜一样,其实她大多数时候都美其名曰为了提高效率,所以,给我五毛钱打发我去买,……,这都什么比喻。Linux中断主要有两种,一个是硬件控制产生的需要CPU给予响应的中断,另外一种是时钟中断。此外,Linux内核的中断处理设计跟我gf一样smart。她特别为了1. 提高系统响应的效率;2. 减轻系统负荷;采取了一种叫做软中断(soft interrrupt)的机制——比如,给五毛钱打发出去打酱油的时候都有一些“乌龙”软语——事实上这是一种将中断延迟处理的机制。

时钟(timer)

Linux自带生物钟。这个时钟主要负责两个任务,1. 时刻;2. 时限;时刻,这个很容易理解么。比如晚上9点1分才回家,她会清楚的知道,并且问你这一分钟究竟上哪里鬼混了。时限,就是你出去打酱油不能超过10分钟就得返回,因为她在家里看秒表。

系统调用(system call)

能够让她帮你做事的唯一交流手段。一般这里的确需要一些鲜花和巧克力,但事实上你得按照和她约定好的方式和她交流,切记“理解万岁”。Linux2.6内核中,内核向普通的用户应用程序提供2种方式的系统调用方式,一种是从Linux诞生以来就有的系统调用方式;另一种是2.6的新特性,在x86结构上可以通过sysenter命令高速执行的系统调用。事实上系统调用在内核中是以一种非常类似于中断处理的方式实现的,甚至可以说系统调用就是用户应用程序(而不是硬件)产生的中断。而系统调用的执行结果,内核通过像普通函数一样的返回值通知用户空间的应用程序。系统调用事实上也是操作系统利用CPU提供的保护模式将内核代码的执行和普通应用程序执行划分开来的结果,由此提高内核的健壮性。受保护的内核代码不会被普通应用程序直接访问,Linux在执行系统调用的时候,她会将改变CPU的执行模式,并在这个模式中执行内核代码。

排他和同期(mutual exclusive & synchronize)

Synchronize这个词事实上原本的意义就是时间上相同,因为它含有一个’chron’词根,这个词根表示时间的意思。跑题了。Linux需要在某些情况下独占资源,又在某些情况下需要协调和同步工作,所以,内核自身必须准备一些机制以保证自身的正常运行。这些包括,1. 信号量(semaphore);2. spin lock;3. RCU-Read Copy Update等等等。总之,这是Linux自身具有的特性,并且是基础特性。

基本上,在内核代码的kernel目录中你可以看到上面提到的这些内容了。因为它们组成了Linux的基础功能,所以通常被合在一起被叫做”Kernel Primitive”。装B的翻译方法通常是“内核原语”,但是我很害怕讲错,所以通常不这么叫它,再次言而总之,这个部分是你只要知道内核的核,就一切OK了。

--
1. Minix却是微内核

4 thoughts on “Linux内核源码阅读系列(2)-内核的构成 之 一

发表评论