为什么要阅读linux内核源码以及如何阅读Linux内核源码

目的:为了更好地编写驱动程序,对自己写的程序有更深入的理解,并且自己的岗位定位在底层。

获取内核源码:

https://www.kernel.org/

阅读linux内核,常用下面两种方法:

1.bochs+linux0.11+书(linux内核完全注释、linux内核完全剖析、linux内核设计的艺术)
2.sourcesinsight+linx2.X+书(linux内核情景分析)

阅读源码分为纵向阅读和横向阅读。纵向就是跟着内核的执行流程来读,横向就是按照内核的各大功能模块来读。

第一种方法纵向或者横向来读都可以,因为代码量不是很大。《linux内核完全剖析》《linux内核完全注释》是引导你横向阅读的书,《linux内核设计的艺术》是引导你纵向阅读的书。个人经验可以横向纵向结合着来,纵向跟着bochs调试工具来是必不可少的,当遇到问题时进入到相应的功能模块横向拓展一下。

《linux内核情景分析》中的内核版本是2.4.X,现代内核版本还是推荐横向阅读,纵向几乎不可能。我在Linux下搭建了quem虚拟机,然后用GDB调试内核也可以。
总之阅读源码的方法也就上面两种,贵在坚持,但是别闭门N久学内核,没有意义。而且长时间只读代码,不敲代码是不行的。

如果想在简历中写上关于linux内核的经验,先不要花大量时间看源码,先把《linux内核设计与实现》读了,在找工作中更有用。

Linux5.4.6

在这里插入图片描述

通常Linux会有以下目录

arch 子目录包括所有和体系结构相关的核心代码。它还有更深的子目录,每一个代表一种支持的体系结构

include 子目录包括编译核心所需要的大部分 include 文件。它也有更深的子目录,每一个支持的体系结构一个。 include/asm 是这个体系结构所需要的真实的 include 目录的软链接,例如 include/asm-i386 。为了改变体系结构,你需要编辑核心的 makefile ,重新运行 Linux 的核心配置程序

init 这个目录包含核心的初始化代码,这时研究核心如何工作的一个非常好的起点

mm 这个目录包括所有的内存管理代码。和体系结构相关的内存管理代码位于 arch/*/mm/

drivers 系统所有的设备驱动程序在这个目录。它们被划分成设备驱动程序类

ipc 这个目录包含核心的进程间通讯的代码

modules 这只是一个用来存放建立好的模块的目录

fs 所有的文件系统代码。被划分成子目录,每一个支持的文件系统一个

kernel 主要的核心代码。同样,和体系相关的核心代码放在 arch/*/kernel

net 核心的网络代码

lib 这个目录放置核心的库代码。和体系结构相关的库代码在 arch/*/lib/

scripts 这个目录包含脚本(例如 awk 和 tk 脚本),用于配置核心

按照以下顺序阅读源代码会轻松点

核心功能(kernel)

内存管理(mm)

文件系统(fs)

进程通讯(ipc)

网络(net)

系统启动和初始化(init/main和head.S)

其他等等

具体分类说明:

  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. 内核
    内核中,特定结构的代码在arch/*/kernel,调度程序在kernel/sched.c,fork的代码在kernel/fork.c,task_struct 数据结构在 include/linux/sched.h中。

  4. PCI
    PCI 伪驱动程序在 drivers/pci/pci.c ,其定义在include/linux/pci.h。每一种结构都有一些特定的 PCI BIOS 代码, Intel的在arch/alpha/kernel/bios32.c。

  5. 进程间通信
    所有System V IPC 对象权限都包含在 ipc_perm 数据结构中,这可以在 include/linux/ipc.h中找到。 System V 消息是在 ipc/msg.c中实现, 共享内存在 ipc/shm.c中,信号量在 ipc/sem.c中,管道在 ipc/pipe.c中实现。

  6. 中断处理
    内核的中断处理代码是几乎所有的微处理器所特有的。中断处理代码在 arch/i386/kernel/irq.c中,其定义子在 include/asm-i386/irq.h中。

  7. 设备驱动程序
    Linux内核源代码的很多行是设备驱动程序。Linux设备驱动程序的所有源代码都保存在/driver,根据类型可进一步划分为:
    /block块设备驱动程序如ide(在ide.c)。如果你想看包含文件系统的所有设备是如何被初始化的,你应当看drivers/block/genhd.c中的device_setup(),device_setup()不仅初始化了硬盘,当一个网络安装nfs文件系统时,它也初始化网络。块设备包含了基于IDE和SCSI的设备。/char这是看字符设备(如tty,串口及鼠标等)驱动程序的地方。/cdrom Linux的所有CDROM代码都在这儿,如在这儿可以找到Soundblaster CDROM的驱动程序。注意ide CD的驱动程序是 ide-cd.c,放在drivers/block,SCSI CD的驱动程序是scsi.c,放在drivers/scsi。/pci这是PCI伪驱动程序的源代码,在这里可以看到PCI子系统是如何被映射和初始化的。/scsi 在这里可以找到所有的SCSI代码及Linux所支持的scsi设备的所有设备驱动程序。/net在这里可以找到网络设备驱动程序,如DECChip 21040 PCI 以太网驱动程序在tulip.c中。/sound 这是所有声卡驱动程序的所在地。

  8. 文件系统
    EXT2 文件系统的源代码全部在 fs/ext2/ 目录下,而其数据结构的定义在 include/linux/ext2_fs.h, ext2_fs_i.h 及 ext2_fs_sb.h中。 虚拟文件系统的数据结构在 include/linux/fs.h中描述,而代码是在fs/*中。 缓冲区高速缓存与更新内核的守护进程的实现是在 fs/buffer.c中 。

  9. 网络
    网络代码保存在/net中,大部分的include文件在include/net下,BSD套节口代码在net/socket.c中,IP 第4版本的套节口代码在net/ipv4/af_inet.c。一般的协议支持代码(包括sk_buff 处理例程)在net/core下,TCP/IP联网代码在net/ipv4下,网络设备驱动程序在/drivers/net下。

  10. 模块
    内核模块的代码部分在内核中,部分在模块包中,前者全部在kernel/modules.c中,而数据结构和内核守护进程kerneld的信息分别在include/linux/module.h和include/linux/kerneld.h 中。如果你想看ELF目标文件的结构,它位于include/linux/elf.h中。

我读过的几本书:

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内核的虚存管理子系统,正如同会讲汉语不说明你懂中国文化一样。

参考:

https://www.cnblogs.com/fanzhidongyzby/archive/2013/03/20/2970624.html

https://www.cnblogs.com/zengkefu/p/5563005.html

在线阅读Linux内核源码网站:

https://elixir.bootlin.com/linux/latest/source

发布了131 篇原创文章 · 获赞 44 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_38769551/article/details/103769074