Java 开发者需要研究 JDK,Linux 开发者需要研究 Kernel
2019 年是 Linux 内核诞生的第 28 年,1991 年 8 月 26 日,当年还是大学生的 Linus Torvalds 向 comp.os.minix 新闻组的成员透露了出于“业余爱好”而正在研究操作系统的消息。
Linux Kernel 是全球最大的开源项目,知名的科技公司几乎都参与其中,包括微软、谷歌、Red Hat、SUSE、Intel、Facebook、百度、阿里、华为、Oracle 与腾讯等。同时,基于 Kernel 衍生出的发行版与各种周边项目也让其生态多姿多彩。
另一方面,在当今云原生高速发展的时代,其底层也大多基于 Linux Kernel,甚至连微软也表示 Linux 运行了 Azure 工作负载的 50% 以上。
Linux Kernel 短期内不会过气,而是会进一步影响到更多开发者,但是 Linux Kernel 的入门和实践却很困难,这让许多初学者望而却步,哪个开发者说自己是 Linux Kernel 领域的,那其他人必定会肃然起敬。
最近了解到有一本值得初学者学习的相关书籍《精通 Linux 内核——智能设备开发核心技术》,我们就如何学习 Linux Kernel、Linux Kernel 2019 年的发展与相关应用领域等问题采访了作者姜亚华,希望能给到想要了解、研究 Linux Kernel 的开发者一些启发。以下是对话内容,姜老师会抽取三位留言的读者送出图书。
2019 年 Linux Kernel 进入了 5.x 时代,虽然 Linus 自己说从 4.20 到 5.x 只是因为自己手指不够用,但是实际上以您的理解,这对于项目的生命周期管理、特性合并或者社区文档建设等方面有没有比较大的影响呢?
姜亚华:
5. x 其实更新蛮多的,patch 文件 40 多 M,涉及 10000 多个文件。
这是一个大版本更新,从用户意识角度来讲,4.x 已经是旧的了,就好像 iPhone 更新,Apple 维持两年一个大更新的节奏,买了一款 iPhone,下一年的小更新不会有啥感觉,但是第二年大更新后,才觉得我的手机不是最流行的了。
新的项目,文档等肯定都需要向 5.x 看齐了。
从代码角度来讲,我们可以从内核更新的过程中学习到很多优化的思路。我开始写作《精通 Linux 内核——智能设备开发核心技术》的时候内核还是 3.x,在书中也刻意保留了部分 3.x 的讨论(sysfs、进场切换等),就是为了通过对比总结这方面的经验。
书中讲到文件系统,但是没有关于最近微软件开放出来的 exFAT,猜想是因为您这书已经在此之前就写了,那目前您有没有继续研究 exFAT 相关的内容呢?目前 exFAT 也已经在 5.4 中支持,它的能力上会带来什么影响呢?
姜亚华:
是的,我接下来打算再深入一些模块,exFAT 是其中之一。它的未来如何还很难说,Linux 已经有很多优秀的文件系统了,它们都经过了多年的验证,bug 可能也相对少一些,exFAT 还需要在 Linux 上经过时间的考验。
近期另一个内核新特性也引起了广泛的讨论,那就是内核锁定,这个特性其实讨论了多年,最后它的表现形式似乎也挺让人不解的。该特性限制了 root 角色的权限,但是 root 是系统的最高级权限都有不能访问的地方,这对于 root 来说是挺奇怪的一件事情,在开发、运维或者日常使用上这会产生什么比较大的影响吗?
姜亚华:
内核锁定主要是为了防止 root 帐户篡改内核代码,从而在用户态进程和代码之间划清界限。启用锁定模块后,各种内核功能都会受到限制。其中包括对内核功能的访问限制;对 /dev/mem 的读写操作的阻止;对 CPU MSR 访问的限制;以及防止系统进入睡眠状态等等。
这对 root 来说其实并不奇怪,它依然是超级用户,可以访问所有正常的门。只不过内核锁定把一些“后门”去掉了,这些门常闭或者不存在了。
引入内核锁定(CONFIG_SECURITY)后,root 的访问受到限制,开发、运维等过程中使用的脚本或者 sequence 可能就不能工作了。比如 root 可以通过 /dev/mem 文件访问内存,引入内核锁定后可能会受到限制。
说句题外话,root 是个挺危险的东西,慎用。记得我负责管理部门服务器的时候,有一次供应商帮我移植驱动的过程中,安装软件的时候不小心删除了一些文件,服务器断电后就无法启动了。我带着光盘,在无数服务器轰鸣的实验室中,花了好几天才将它“抢救”回来。
相信很多开发者,或者刚在大学学计算机的人在了解了 Linux Kernel 之后都会想要去读它的源码,但是应该大部分都会不得其法,最终放弃。您是怎样阅读 Linux 内核源码的呢?有什么工具、方法与其它经验可以分享?
姜亚华:
我也是一行一行代码看下来的,几点建议供大家参考。
首先,先大概弄清原理,再仔细研究代码,事半功倍。对于已经成熟的模块,可以先借助书籍和博客大致理解它的基本信息。
其次,边读代码边做笔记,防止看了后面忘记前面。做笔记的软件蛮多的(比如微软的 OneNote),选择用的习惯的就好。
最后,自我激励,坚持到底,最好是兴趣使然。
好在大家不需要从头开始了,我已经把自己看过的代码的截图放在随书资料中了,算是一小段捷径吧。这些截图里面,某函数、它调用的函数等函数调用关系使用红线标示(如下图),内容包括内存管理、文件系统和进程管理三大模块。
大家遇到疑问也可以联系我,共同探讨,OSC 站内信(always_first_meet)或者邮件([email protected])都可以。
Linux 内核十分庞大,阅读源码的时候哪些部分是最开始的时候必须的,而哪些部分可以作为后续针对性的补充?
姜亚华:
内核代码量庞大,模块间的关系也错综复杂,建议初学者可以从相对简单而且独立的模块入手,比如一个简单设备的驱动。
先了解驱动本身的逻辑,之后是它的上下游,然后扩展到相关模块,最后自由发挥。
举个例子,在 drivers/input/keyboard 下面的文件是键盘驱动,我们选择一个文件。
第 1 阶段,查看 xxx_probe 等函数,梳理控制和数据流程,理解驱动需要做什么。
第 2 阶段,适当拓展,代码内调用的函数大概是如何实现的,驱动涉及的中断、定时器、input 子系统等机制的原理,这些机制相对独立,文档也多,多花些时间即可。
第 3 阶段,追根溯源,研究 xxx_probe 是如何被调用的,i2c 总线的驱动(假设键盘接 i2c 总线),device/device_driver/bus 的关系(驱动架构)。
阶段 2 与 3 可以同时进行。
第 4 阶段,自由发挥,按照工作需要和兴趣,进军内存管理、文件系统和进程管理等模块。
就算是能够阅读源码,另一个问题也会出现,就是读了源码,理解了它的逻辑,但是有什么用呢?最简单的是增长了自己的见识,但是实际上这就像阅读了一本书但是不输出自己的理解与观点,没有太大的作用。您是怎么看待并且怎么解决这个问题的呢?
姜亚华:
研究内核有什么用,这是一个值得深思的问题。
中国现在这个时候的确需要沉下心玩底层系统的人,中国渴望自主操作系统已经很久了,尤其是现在这种多事之秋。但是如果没有大批工程师在这个领域积淀的话,操作系统无疑是一种空谈。
先不论未来的国产操作系统是否一定是 Linux 内核的,研究 Linux 内核本身也是很好的技术积累途径。
仅仅从个人职业生涯角度出发,研究内核对个人技术的成长有极大帮助,可以分多个层次看待。
第 1 层次,初识,对内核有大概的了解,需要花时间深入工作相关的模块。研究内核会占用大量时间,产出并不明显。
第 2 层次,入门,熟悉工作相关的模块,理解内核模块间的关系。研究内核会让你豁然开朗,经常有“原来 xxx 是这么实现的”之类的感叹。
第 3 层次,熟悉或精通,对内核常用模块有一定研究,熟悉代码。即使是新模块,也可以快速厘清脉络。
除了第 1 层次“浪费”时间外,花时间研究内核可以反过来提高我们的效率。研究到了一定程度后就可以进入一个良性循环,研究得越多,效率越高,节省的时间越多,可以研究的越多。
另外,看的代码越多,越有能力解决错综复杂的问题,金老爷子也说“重剑无锋,大巧不工”,绝对的实力才是硬道理。
还是 xxx_probe 的例子,如果我们的 probe 没有被调用,新手可能会检查 device 和 device_driver 的名字是否匹配,研究过驱动架构的工程师可能分 device、device_driver 和 match 三部分检查。
如果三部分看似都没有问题,但是 probe 依然没有调用呢?研究过代码的工程师可能会想到 device 是不是已经和另一个 device_driver 匹配了。
经验可以帮助我们看到问题的关键部分,真正研究过代码才能看到问题的本质。庖丁看到的不是牛,而是肌理结构,到了这种境界换成羊也是一样的。
最近经常听到一句话,“工作 xx 年,就是一年的工作经验重复 xx 年”,如果只是要求“会用”的层次,的确一年足够,但工程师在这种情况下早晚会失去核心竞争力。
有人倾向于使用结论,但要做的应该是总结和解释结论。
现在学习 Linux Kernel,主要有哪些工作方向呢?又是哪些类型的公司、业务会主要需要这种能力?
姜亚华:
驱动工程师、嵌入式工程师、系统工程师、Linux 程序开发工程师,甚至运维工程师这些岗位都需要了解内核,就像从事 Java 开发的工程师需要研究 JDK 一样,并不是只有从事内核相关工作的工程师才需要研究内核,反过来懂内核的人向上发展也是很容易的。
有半导体相关业务的公司都需要这类人才,以前传统的半导体公司需求大一些,但近几年互联网公司也纷纷涉足半导体领域,BAT 都包括在内。美国一系列动作之后,近期中国进入了芯片和操作系统研发热潮,一大批芯片公司成立,燧原、平头哥、寒武纪与商汤科技等等,它们也都需要内核相关的人才。
您这本书讲到关于智能设备的开发,Linux Kernel 与 AI 有什么特别大的关系呢?
姜亚华:
其实这个问题我在这次写的书里有解释。
如上图,“硬件厂商负责硬件,原语(primitives)库一般也由他们维护,比如 AMD 的 MIOpen、Intel 的 MKL 和 Nvidia 的 cuDNN,多数程序员并不会接触这部分内容,而是使用已有的 Framework。
Framework 的选择也是多样化的,Google 的 TensorFlow,Facebook 的 PyTorch,微软的 CNDK,亚马逊的 MXNet、Theano 和 Keras。很明显,目前依然是百花齐放的局面,但技术的发展终归只能是“三分天下”,甚至是“一统天下”。目前已经存在与这些 Framework 配套的工具,比如 Tensorboard,可以用来查看 TensorFlow 的训练状态。
由于深度学习计算量太大,并行计算技术也会有所涉及,比如 MPI(Message Passing Interface)通信协议、英伟达的 NCCL(NVIDIA Collective Communications Library)。
数据对深度学习十分重要,大数据是必不可少的。数据作为输入,模型作为输出,应用于数据中心、个人计算机、机器人和无人驾驶汽车等设备中。
纵观这整个过程,并没有哪一个环节提到了 Linux,但实际上多数环节都与 Linux 有关。虽然这些关系可能只有少数程序员关注,但随着技术的成熟,新的智能设备,甚至新的操作系统,又会转回到我们熟悉的内核。
在您研究 Linux 内核的过程中,有没有觉得 Linux 内核其实还可以用其它语言实现一次,这样对于入门学习会好很多,比如用 Python 这种简单理解的语言。这样的想法可行吗?会遇到什么技术问题?
姜亚华:
内核里面有很多代码采用的都是面向对象的思想,比如 VFS 采用了较多面向对象程序的设计模式,像 command 与 template method 等,使用其它语言尤其是面向对象语言来实现 Linux 内核是可行的,但是不得不说的是其它语言(比如 Python)很难有 C 语言的执行效率。
2019 年是 Linux Kernel 28 周年,分享一下您在这其中关于 Linux Kernel 印象最深的事情吧。
姜亚华:
Linux 内核是开源的,天生与微软(更确切的说是 Windows)就是宿敌。微软对 Linux 前期的敌对和近些年的转变是件很有趣的事情,敌对时期就不多说了,近几年微软宣布“爱 Linux”,也做了很多实事,Azure、SQL Server 和 Visual Studio Code 等都有了 Linux 的身影。
这对 Linux 是好是坏先不说,这起码说明了 Linux 的强大,有种“东方教主,千秋万代,一统江湖”的感觉哈哈。
这是一件关于 Linux Kernel 印象比较深的事情,还有另一件也值得一提,那就是我今年写了一本 Linux Kernel 相关的书籍《精通 Linux 内核——智能设备开发核心技术》,借此也宣传宣传,同时希望能够通过这本书为道友们提供些许帮助。
这本书基于 Linux 5.x,历时五年,研究数百万行代码总结而成,共分为五个部分,按照先易后难的顺序剖析内核。首先介绍基础知识,包括数据结构、中断处理、内核同步和时间计算等,它们是理解后续章节的前提,在此基础上详细讨论内存管理、文件管理和进程管理三个核心模块,最后一部分升华篇融合了前面多个模块。重点和难点部分均配以图表、代码或实验,力求深入浅出。
除此之外,本书列举了大量实例,分析了安卓操作系统的核心技术,使读者能够深刻的理解理论知识。本书的读者需要熟悉 C 语言,能够对内核有一定了解更好。推荐初学者按照本书的既定顺序阅读,熟悉内核的读者可以直接阅读三个核心模块。
当然了,借这个平台,也希望与道友们多多交流(包括但不限于本书的内容),欢迎大家跟我交流共同促进。另外本书是机械工业出版社《Linux 技术与应用丛书》的开篇之作,后续还会有一系列书籍出版,大家也可以关注关注。