奔跑吧 Linux内核
上QQ阅读APP看书,第一时间看更新

前言

近些年来,使用安卓操作系统的智能手机热销,未来也将是物联网、大数据、云计算的大时代,而运行在这些相关产品最深处的几乎都是Linux内核。我一直在凝望你,你看不见我,我是谁?我是奔跑中的Linux内核小企鹅。

说起和Linux的渊源,要追溯到十几年前的大学时代了。2002年,正在读大二的我购买了人生第一台电脑,AMD的毒龙CPU,在同学的指导下安装了RedHat 9,这是我第一次接触Linux操作系统。从此,我就被Linux系统深深地吸引了,乐不思疲地折腾着我的RedHat 9。2004年春天在实验室忙着做毕业设计时,蓦然回首看到小伙伴桌上有两本厚厚的《Linux内核源代码情景分析》,我再次被深深地吸引了,心里嘀咕着不知道什么时候才能看得完和看得懂。到了2017年的今天,已经毕业12年多了。12年的光景让我从一名大学生变成了“笨叔叔”,也让Linux内核这个小企鹅变成今日的科技明星。与12年前相比, Linux内核代码已经发生了翻天覆地的变化,但是不变的是一群热爱Linux内核的小伙伴,那是一群奔跑着的年轻人。《Linux内核源代码情景分析》这本书在Linux内核圈里被称为经典,可是它讲述的内核版本是2001年发布的Linux 2.4.0,距今已经有16年了。

回顾学习Linux内核的那段经历,我愈发体会到Linux内核的功夫在Linux内核之外。Linux内核变得越来越庞大,特别是现在硬件的发展速度非常快,各种不同的思想和实现如雨后春笋一般,各种各样的补丁也让人眼花缭乱。对于一个初学者或者有经验的工程师来说,要阅读和理解最新版本的Linux内核变得越来越困难。而且现在市面上Linux内核书籍都比较旧,最经典的《深入理解Linux内核》讲述的是Linux 2.6.11内核,它发布于2005年,《深入Linux内核架构》中讲述的Linux 2.6.24内核是2008年1月发布的。以每2~3个月发布一个Linux内核新版本的速度,这些书中的内核版本与当前的4.x内核不可同日而语。另外,我发现身边不少朋友很想把Linux内核吃透,然后购买了不少Linux内核的书籍,但有时好几天也没读几页。究其原因是,现在市面上已有的Linux内核书籍大多是教科书式地讲述知识点,机械式地讲述内核代码的实现,读起来很容易让人犯困。

Linux内核代码由一个一个补丁组成,这些补丁都是为了解决某个问题或者添加某些新的功能,因此最好的学习方法是:理解代码是为了解决什么问题,如何解决的,要了解问题的来龙去脉。对于学习Linux内核这件事情来说,应该和孩提时读“十万个为什么”一样,以问题为中心,通过阅读代码和书籍来寻找答案,比如你在用C语言写一个很简单的程序时,应该想想malloc何时分配出物理内存。当你带着疑问去阅读代码以及独立思考之后,会得到一种享受和愉悦,这就是我说的“Linux内核的功夫在于内核之外”。因此,站在设计者的角度来提出疑问,进而阅读代码和分析推理求索之后,终于有种“拨开迷雾见天日”的喜悦。

本书特色

1.问题导向式的内核源代码分析

Linux内核庞大而复杂,任何一本厚厚的Linux内核书籍都可能会让人看得昏昏欲睡。因此本书想做一个尝试,总结我多年来在学习Linux内核代码和实际工程项目中遇到的比较常见的疑问,以疑问为中心讲述内核代码。在讲述每章之前,首先列举出一些思考题,激发读者探索未知的兴趣。

这些思考题主要来自于如下3个方面。

❑ 从我多年来实际工程项目中遇到的问题抽象出来。我们在实际产品的研发过程中,比如手机项目研发或者其他智能产品的研发,难免要编写驱动或者系统优化,那么常常会遇到一些问题。如果对内核了解很透彻,解决问题的速度也会明显提高。例如在书中提到的驱动代码内存越界访问的问题,如果对内存管理和内核调试很熟悉,可能用几个小时就能修复bug了,如果换成一个不熟悉的工程师也许耗费很长时间还是找不到方向。系统中一些问题可能会是定时炸弹,随时可能引爆,因此绝大多数情况下,查找问题花费的时间要远远多于提前静下心来搞懂\2inux内核机制的时间。

❑ 我在阅读内核代码时产生过的一些疑问。

❑ 我和身边的朋友在参加面试时经常会被问到的有关Linux内核的问题。

2.力求反映Linux内核社区最新的开发技术

本书基于Linux 4.x内核,我会在每章末尾尽量把内核技术的最新发展情况分享给读者。另外,我也会加入一些最新的热点话题,比如内存管理漏洞——Dirty COW的分析;手机领域最新Android 7.1.1版本中的EAS节能调度器、WALT算法、PELT算法改进、Queued Spinlock等。

3.Linux内核奔跑卷

本书开篇会提供一份Linux内核奔跑卷,这也是Linux内核书籍中一个新的尝试。读者可以将其用于Linux内核水平测试或面试题目,我希望能给读者带来阅读Linux内核的兴趣和探索知识的乐趣。

4.QEMU调试环境和内核调试技巧

在阅读Linux内核时,大多数人都希望有一个功能全面且好用的图形化界面来单步调试内核。本书中会介绍一种图形化单步调试内核的方法,即Eclipse+QEMU+GDB。另外,本书提供首个采用“-O0”编译和调试Linux内核的实验,这样可以解决调试时出现光标乱跳和<optimized out>等问题。本书也会介绍实际工程中很实用的内核调试技巧,例如ftrace使用、systemtap、内存检测、死锁检测、动态打印技术等,这些都可以在QEMU+ ARM Linux的模拟环境下做实验。

5.ARM32和ARM64体系架构

本书以ARM32和ARM64体系架构为蓝本,介绍Linux内核的设计与实现。

本书主要内容

Linux内核涉及的内容包罗万象,但本书不想成为一本大而全的书,因此只选取了最基本最常用的内存管理、进程管理、并发与同步和中断管理这4个内核模块进行讲述,力求把我所理解的东西完整记录下来。

本书中每节的内容都是一个Linux内核的话题或者技术点,在每节开始之前会先提出若干个问题,读者可以根据这些问题先思考,然后围绕这些问题进行内核源代码的分析,最后是对相应内容的一个小结。

Linux内核奔跑卷一共20道题目,每题10分,一共200分,读者可以在2小时内完成。

第1章处理器体系结构。简单介绍ARM32和ARM64结构中一些比较常见的问题,例如cache组织架构、cache一致性管理、页表访问、MMU、内存屏障等与体系结构相关的内容。

第2章内存管理。包括物理内存初始化、内存分配、伙伴系统、slab分配器、malloc内存分配、mmap系统调用、缺页中断、匿名页面的宿命、物理页面page结构、反向映射、页的迁移、KSM、DirtyCOW、页面回收、内存管理数据结构框架等内容。

第3章进程管理。包括fork系统调用、CFS调度器、PELT算法改进、SMP负载均衡、HMP调度器、WALT算法、EAS绿色节能调度器等内容。

第4章并发与同步。包括原子变量、spinlock、信号量、读写信号量、Mutex、RCU等内容。

第5章中断管理。包括硬件中断处理、软中断、Tasklet、workqueue等内容。

第6章内核调试。包括内核单步调试、ftrace使用、systemtap使用、内存检测、死锁检测、动态打印技术等内容。

本书罗列的内核代码均为代码片段,显示的行号也并非源代码的实际行号,只是为行文描述方便。另外,在实际代码中有大量的注释,本书为了节省篇幅而省略了大量的代码注释,建议读者对照代码来阅读。

本书在实际代码讲解时还列举了一些关键的patch,阅读这些patch有助于帮助读者理解代码。建议读者下载官方Linux的git tree。下载代码命令如下:

      #git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
      #git reset v4.0 -hard


列举的patch格式如下:

Linux2.6.29, commit bf3f3bc5e, <mm: don't mark_page_accessed in fault path>, by Nick Piggin.

表示在Linux 2.6.29中加入了此patch, git commit的前几位ID号是“bf3f3bc5e”,读者可以通过“git show bf3f3bc5e”命令来查看该patch,该patch的标题是“<mm: don't mark_page_accessed in fault path>”,作者是Nick Piggin。

由于作者知识水平有限,书中难免存在纰漏和理解错误之处,敬请各位读者朋友批评指正。我的邮箱:runninglinuxkernel@126.com。新浪微博:@奔跑吧Linux内核。大家也可以扫描下方的二维码,到我的微信公众号中提问和交流。

关于作者

本书作者从事Linux内核和驱动开发十余年,是Linux内核的爱好者,曾在多家芯片公司从事过手机芯片底层软件开发和客户支持工作。

写一本Linux内核方面的书籍是笔者多年来的一个小心愿。本书取名为《奔跑吧Linux内核》,一是Linux内核在蓬勃发展,全球众多杰出的公司和开发者都在为Linux内核社区开发令人激动的新功能;二是我们要不断地向前狂奔才能赶上Linux内核发展的步伐;三是作者有一个人生目标,希望每天能坚持奔跑5千米,直到80岁,因此作者希望和广大读者共勉。在开始撰写本书时Linux内核版本才到4.0,完稿时Linux内核已经发展到4.10版本了,作者选择一个整数版本Linux 4.0作为本书学习和分析的版本。谭校长有一首歌叫《八十岁后》,歌词是“总相信,八十岁后,仍然能分享好戏”,他坚持要开演唱会到八十岁。我也有一个小小的目标,希望日后Linux内核发展到5.0、6.0……版本时,《奔跑吧Linux内核》依然能以最快的速度修订和大家见面。

致谢

几经放弃,几经坚持,听着Beyond的歌,咬着冷冷的牙,坚持着心中那个万里奔跑的信念。在繁忙工作之余写书是很枯燥的,但是期间我得到了众多Linux内核社区朋友的热心帮助和鼓励。特别是陈绪、吴峰光、Tim Chen、肖光荣、李泽帆、Waiman Long、冯博群、谢宝友、杜雨阳、郭健、孟卫国、修志龙、朱辉、宋宝华、吴章金、王齐、薛坤、刘勃、刘杰、郭哲佑、郭雄飞以及胡振波,他们为本书审阅了全部或者部分稿件,提出了很多很好的意见和建议。另外还要感谢石庆、Fane Li、Law Hock Yin、周祥、何章龙、杜秉权、杨永刚、张思超、段夕华、周琰玉、涂小兵、杨晨星、杨冬冬、孟皓、王建强、王智、宋吉科、何刘宇、Tian Jun等给予的帮助。感谢南京大学软件学院的夏耐老师在KSM项目中的指导,让我对Linux内核内存管理有了更深刻的理解和认知,还要感谢任德志老师的鼓励和帮助。

本书在编写过程中得到了Linux内核社区众多杰出华人开发者以及maintainer(维护者)的鼓励和帮助,他们仔细审阅本书并提出了独特的见解和建议,这些都是无价的。在此再一次表达我的感激之情,他们都是Linux内核社区最杰出的华人代表(排名不分先后)。


陈绪 中国开源软件推进联盟常务副秘书长。


吴峰光 Linux内核社区资深技术专家,0-day内核测试项目的发起人,其预读算法和回写算法享誉内核社区。


肖光荣 Linux内核社区资深技术专家,KVM社区和Qemu社区的核心开发者和maintainer。


Tim Chen Linux内核社区资深技术专家,Linux MCS锁和Mutex自旋等待机制的作者。


Waiman Long RedHat公司Linux内核资深技术专家,Linux内核著名的锁专家,为读写信号量、Mutex和Queue Spinlock等做出杰出的贡献。


李泽帆 华为资深Linux内核技术专家,Cgroup及cpuset模块的co-maintainer。


谢宝友 Linux内核社区ZTE平台维护者,中国开源软件推进联盟专家委员,《深入理解并行编程》译者。


郭健 Linux内核资深技术专家,技术网站蜗窝科技创始人。


冯博群 Linux内核社区资深技术专家。


孟卫国 Linux内核资深技术专家。


杜雨阳 Linux内核社区CFS调度器专家,为CFS中的PELT算法做出重大优化和贡献。


修志龙 ARM公司应用工程师经理,精通Cortex系列处理器架构。


王齐 计算机体系结构资深技术专家,著有《Linux PowerPC详解——核心篇》和《PCI Express体系结构导读》。


宋宝华 Linux内核资深技术专家,ARM Linux社区maintainer,著有《Linux设备驱动开发详解》。


吴章金 魅族手机研发中心BSP部技术总监。


刘杰 百度主任研发架构师,Linux内核资深技术专家,XFS文件系统核心开发者。


朱辉 小米科技Linux内核技术资深专家,KGTP项目发起人,GDB项目的maintainer。


夏耐 南京大学计算机博士,操作系统资深专家。


感谢我的领导Liu Song先生和Luebbers Enno先生对我的支持和帮助。同时感谢人民邮电出版社的张涛和张爽两位编辑的辛勤付出,才让本书顺利出版。最后感谢我的家人对我的支持和鼓励,虽然周末时间都在忙于写作本书,但是他们总是给我无限的温暖。

致敬

浙江大学计算机学院是全球最早开始从事Linux内核研究和教学的高校之一,非常感谢陈文智院长为本书作序,陈老师一直持续关注和鼓励本书的编写和出版,给了我很多指导性的意见和建议。

毛德操和胡希明老师编写的《Linux内核源代码情景分析》一书是中国Linux内核发展史上一个永恒的经典,在此向这两位老学者和前辈致敬。此时此刻,脑海里响起了一首歌:“一追再追,只想追赶生命里,一分一秒”。愿和大家一起奔跑、一起追赶、不浪费生命的一分一秒。

张天飞

2017年夏于上海