Linux 内核编程学习

Linux  内核编程学习


常常有人问:我想学习内核,需要什么基础吗?Linus Torvalds 本人是这样回答的:你必须使用过 Linux 。 这个 …… 还是有点太泛了吧,我想下面几个基础可能还是需要的,尽管不一定必需:

1, 关于操作系统理论的最初级的知识。不需要通读并理解《操作系统概念》《现代操作系统》等巨著,但总要知道分时( time-shared )和实时( real-time )的区别是什么,进程是个什么东西, CPU 和系统总线、内存的关系(很粗略即可),等等。

2, 关于 C 语言。不需要已经很精通 C 语言,只要能熟练编写 C 程序,能看懂链表、散列表等数据结构的 C 实现,用过 gcc 编译器,就可以了。当然,如果已经精通 C 语言显然是大占便宜的。

3, 关于 CPU 的知识。这块儿可以在学习内核过程中补,但这样的话你就需要看讲解很详细的书,比方后面将会提到的《情景分析》。你是否熟悉 Intel 80386 CPU ?尝试着回答这几个问题来判断一下: 1 )说出 80386 的中断门和陷阱门的区别; 2 )说出保护模式与实模式的区别; 3 )多处理器机器上,普通的读 - 写回一块内存这样的动作,为什么需要特殊的手段来保护。等等。讲解基于其它 CPU Linux 内核的书,目前好象只有一本 IA-64 Linux  内核设计与实现》 也还是 Intel 的,其它都是讲解基于 IA32 的。

以上算是知识方面吧,如果还要再补充一条,我想就是:动手编译过内核。

好了,我们接下来走。好多人装上Linux 之后,第一件事找到内核源码所在的路径,打开一个 C 程序文件,开始哗哗哗翻页,看看大名鼎鼎的 Linux 内核代 码到底长啥模样 ── 然后关闭。这是可理解的,但却不是学习的方法。刚开始,必须从读书入手。至少要对内核有一个 Overview 之后,才有可能带着问题去 试图阅读源代码本身。下面就讲一下我读过的几本书:

1,  Linux 内核设计与实现》,英文名 Linux Kernel Development (所以有人叫它 LKD ),机械工业出版社,¥ 35,  美国 Robert Love 著,陈莉君译者。 评说:

此书是当今首屈一指的入门最佳图书。作者是为2.6 内核加入了抢占的人,对调度部分非常精通,而调度是整个系统的核心,因此本书是很权威的。这本书讲解浅 显易懂,全书没有列举一条汇编语句,但是给出了整个 Linux 操作系统 2.6 内核的概观,使你能通过阅读迅速获得一个 overview 。而且对内核中较为 混乱的部分(如下半部),它的讲解是最透彻的。对没怎么深入内核的人来说,这是强烈推荐的一本书。

翻译:翻译水平、负责任程度都不错,但是印刷存在一些错误。买了此书的朋友可以参考我在Linux 高级应用版的《 Linux 内核设计与实现中文版勘误》:

http://bbs.chinaunix.net/forum/viewtopic.php?t=541234

另外,此书2005 年有了第二版,目前尚无中译本面世。我就是对照着 2nd-en 勘误 1st-cn 的。

2,  Linux 内核源代码情景分析》上、下。毛德操、胡希明著,浙江大学出版社,上册¥ 80, 下册¥ 70.  评说:

本书是基于2.4.0 内核的,比较早,也没听说会出第二版。上册讲解内存管理、中断、异常与系统调用、进程控制、文件系统与传统 Unix IPC ;下册讲解 socket 、设备驱动、 SMP 和引导。关于这套书的评价褒贬不一,我个人认为其深度是同类著作中最优秀的。本书基于 Intel IA32 体系,由于厚度大,很多体系上的知识都捎带讲解了,所以如果你想深入了解内核的工作机制而又不非常熟悉 Intel CPU 的体系构造,本书是最合适的。缺点是:版本较老,没有 TCP/IP 协议栈部分(它讲的 socket 只是 Unix 域协议的),图表太少,不适合初学者 入门。还有就是对学生朋友来说,可能书价偏高,这样的话可以考虑先买上册,因为上册是核心部分,下册一大部分都在讲具体 PCI/ISA/USB 设备的驱 动。

翻译:没什么翻译,作者是国人,而且行文流畅。本人书桌上诸多计算机经典图书当中,这套是唯一又经典又无阅读障碍的。

www.linuxforum.net内核版好多朋友已经把这书读到六七遍了,我很惭愧,上册差不多读熟了,下册就 SMP 部分还看过 ── 但这就花费了整整  1 年的时间,还有好多弄不懂的。这里顺便说明另外一个研究内核常见的误区:目标太庞大。要知道 Linux 内核(最新的 2.6.13 bzip2 压缩之后  37M ,解压缩之后 244M ,根本不是哪个人能够吃透的。即使是内核的核心开发团队中,恐怕也只 Linus Torvalds Alan Cox David Miller Ingo Molnar 寥寥数人会有比较全面的了解,其它人都是做自己专门的部分。 我自己来说,目前已经决定放弃内存管理的全部(slab 层、 LRU rbtree 等)、文件系统部分、外设驱动部分,暂时也没打算弄 IA32 以外的其它体 系的部分。

3, 《深入理解 Linux 内核》第二版。中国电力出版社。也是陈莉君译。此书是 Linux 内核黑客在推荐图书时的首选。 评说:

此书C 版的 converse 兄送了我一本第一版,因此就没买第二版,比较后悔。因此只就第一版说一说,第一版基于 2.2, 第二版 2.4  。我见 O'Reilly 官方主页上说第三版的英文版将于 2005 11 月出版,也不知咱们何时才能见到。此书图表很多,形象地给出了关键数据结构的定义, 与《情景分析》相比,本书内容紧凑,不会一个问题讲解动辄上百页,有提纲挈领的功用,但是深度上要逊于《情景分析》。

4, 其它的几本书。市面上能见到的其它的 Linux 内核的图书,象《 Linux 设备驱动程序》、《 Linux 内核源代码完全注释》以及新出的《 Linux 内核分析及编程》等。

Linux 设备驱动程序》第二版是基于 2.4 的,中文翻译不错,中国电力出版。这书强调动手实践,但它是讲解 设备驱动 的,不是最核心的东西,而且有 些东西没硬件的话无法实践,可能更适合驱动开发的程序员吧,不太适合那些 For fun and profit 的人。此书有第三版英文版,东南大学出版社影印,讲解 2.6 的,行文流畅,讲解的面也比第二版更广泛,我读过其中关于同步与互斥、内存分配的 部分,感觉很不错。

Linux 内核源代码完全注释》(机械工业出版社)是同济大学的博士生赵炯的著作,讲解 0.1Linux 内核,我没买也没看,有看过的朋友说一说。

Linux 内核分析及编程》(电子工业出版社)是刚刚出版的,国人写的,讲解 2.6.11  。很多人说好,但有人说不够系统,我没买,不敢评说。

还有一本清华出的《Linux 内核编程指南(第三版)》,原书应该是好书,但是翻译、排版十分糟烂,脱字跳行,根本没法看,我买了一本又扔掉了。

5, 其它资源。  TLDP The Linux Documentation Project )有大量文档,其中不少是关于内核的,有些是在国外出版过的,象《 Linux Kernel Interls 》《 The Linux Kernel 》《 Linux Kernel Module Programming Guide 》等,作者都是亲身参加开发的人,著作较为可信。

Http://www.linuxforum.net中国 Linux 论坛的内核版。该版是研究内核的中文 Linux 社区中水平最高的,有很多专家级别的牛人,强烈推荐去学习一下(但建议不要问太过分简单的问 题,人家脾气再好也会烦的 ^_^ ),它的置顶贴简直是一个包罗万象的 FAQ ,精华区也有很多资料。只可惜太过曲高和寡,人气不是很旺。

6, 一本不是讲解 Linux 的书:《现代体系结构上的 Unix 系统:内核程序员的 SMP Caching 技术》,人民邮电出版社 2003 版,定价¥ 39.  本书虽然不是讲解 Linux ,但是对所有 Unix 内核都是适用的,适合对 SMP CPU Cache 这些组成原理知识不是很熟的朋友,而且是很多国外牛人 推荐的书。中文版翻译非常负责。

还有个很重要的问题:怎样浏览内核源代码。有的朋友喜欢在Windows 上工作,用 Source Insight ;有的在 Linux ,用 Source Navigator ;还有专门浏览源代码的软件,象 lxr Linux Cross Reference );还有用 ctags/ectags/cscope 等,这些都是很优秀的软件。我个人用 Vim ctags 浏览(参考了 www.linuxforum.net 内核版 wheelz 大侠的文档,)。

此外,前边已经提到的一个重要的问题是:你研究内核的目的是什么, 开发? 乐趣?如果是开发,而且是国内做开发,把kernel API 熟悉一下就差不太多了(你也知道国内的水平有多差),比方说 copy_from_user() kmalloc() 函数等, kernel API Internet 上找得到,编译内核时也可以用 DocBook 生成(具体请参考内核源代码包下的 README 文件);如果是研究,那就差别很大 了,需要下很大的苦功:会用 kmalloc() 绝不说明你懂得 Linux 内核的虚存管理子系统,正如同会讲汉语不说明你懂中国文化一样。

说完了,发现前面讲的太罗嗦了,简化一下:

1.  动手编译内核

2.  精读《Linux 内核设计与实现》

3.  www.linuxforum.net 内核版看置顶贴与精华区

此外就凭自己兴趣选择吧。

下面是一篇没写完的《Linux 内核模块编程入门》,不补写了,将就着看吧。

Linux内核模块编程范例

看到昨天有好几个问linux 内核编程问题的帖子,不少是卡在了入门问题上,就整理一下入门的初步流程。针对 2.6 内核的 Linux 系统,需要你的机器上已经安装了 kernel-devel 这个包,也就是编译模块所必须的东西:内核的头文件和一些 Makefile

一、Hello World 程序

/*file: hello.c*/

#ifndef __KERNEL__

#define __KERNEL__

#endif

#ifndef MODULE

#define MODULE

#endif

#include

#include

#include

static int hello_init(void)

{

printk(KERN_ALERT "Hello, The fucking crazy world/n");

return 0;

}

static void hello_exit(void)

{

printk(KERN_ALERT "Bye, The fucking crazy world!/n");

}

module_init(hello_init);

module_exit(hello_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("albcamus ");

2.6内核的 kbuild 子系统跟 2.4 相比有本质的改变。我们下面尝试两种方式编译这个程序:

1, 你可以在本目录下这样写一个 Makefile

obj-m := hell.o

clean:

rm -rf *.o .*.cmd *.ko *.mod.c .tmp_versions

然后用这样的命令行编译:

make -C /lib/modules/`uname -r`/build M=`pwd` modules

这时ls 一下,就能看到生成了很多文件,其中 hello.ko 就是我们需要的内核模块。

2, 专业点儿, Makefile 这样写:

obj-m := hello.o

KERNELBUILD := /lib/modules/`uname -r`/build

default:

make -C $(KERNELBUILD) M=$(shell pwd) modules

clean:

rm -rf *.o .*.cmd *.ko *.mod.c .tmp_versions

然后只要make 一下就可以了。

插入模块用insmod 命令:

insmod ./hello.ko

这时候大家可能会问:为什么我的屏幕上没有见到输出?这个是console 的日志记录级别和你 printk 消息时指定的级别(本例中指定为  KERN_ALERT ,为次高,仅次于 KERN_EMERG )决定的。无论如何,你可以 tail  或者 cat 看看系统日志的最后几行,系统日志一般为 /var/log/messages ,或者直接用 dmesg 命令,肯定能看到输出了。

头文件问题

C程序员都知道,要使用某个外部的函数,应当 #include 某个头文件,这个头文件包含了那个函数的原型 (prototype) 。内核的头文件在  include/ 下,其中 include/asm 是个符号链接,指向你所用内核的具体的体系结构目录,比方说我的系统是 i386 的,那么 include /asm 就指向 include/asm-i386 

内核编程中我们不能链接libc 库,不能使用 libc 库中的函数,所以很有些麻烦。一些重要的函数,象 strcpy/strcmp/snprintf  等, kernel 也为我们实现并导出( export )了,而我们需要 #include 相关的头文件,在 include/linux include /asm 中,你需要自己寻找你所要使用的函数在哪个头文件中声明,并将其 #include 进来。

你可能感兴趣的:(Linux 内核编程学习)