内容简介
本书从工业需求角度出发,注重效率和实用性,是帮助内核研发及调试、驱动开发等领域工程师正确认识并利用Linux内核的难得佳作!作者是腾讯公司的Linux内核专家和存储系统专家,在该领域工作和研究的10余年间,面试了数百位Linux内核工程师,深知学习Linux内核过程中经常遇到的困惑,以及在工作中容易犯的错误。基于这些原因作者撰写了本书。本书出发点和写作方式可谓独辟蹊径,将Linux内核分为两个维度,一是基础部分和应用部分,二是内核架构和内核实现,将两个维有机统一,深入分析了Linux内核的文件系统、设备驱动的架构设计与实现原理。
全书在逻辑上分为三部分:第一部分(第1~2章)先将内核层划分为基础层和应用层,讲解了基础层包含的服务和数据结构,以及应用层包含的各种功能,然后对文件系统的架构进行了提纲挈领的介绍,为读者学习后面的知识打下基础;第二部分(第3~9章)从设备到总线到驱动,逐步深入,剖析了设备的总体架构、为设备服务的特殊文件系统sysfs、字符设备和input设备、platform总线、serio总线、PCI总线、块设备的实现原理和工作机制;第三部分(第10~13章)对文件系统的读写机制进行了深入分析,通过一个真实文件系统ext2,复习本书所有知识点。
目录
目 录
前 言
第1章 内核的基础层和应用层 1
1.1 内核基础层提供的服务 1
1.1.1 内核中使用内存 2
1.1.2 内核中的任务调度 2
1.1.3 软中断和tasklet 3
1.1.4 工作队列 4
1.1.5 自旋锁 5
1.1.6 内核信号量 5
1.1.7 原子变量 5
1.2 内核基础层的数据结构 6
1.2.1 双向链表 6
1.2.2 hash链表 6
1.2.3 单向链表 7
1.2.4 红黑树 7
1.2.5 radix树 7
1.3 内核应用层 8
1.4 从Linux内核源码结构纵览内核 9
1.5 内核学习和应用的四个阶段 10
1.6 本章小结 11
第2章 文件系统 12
2.1 文件系统的基本概念 12
2.1.1 什么是VFS 13
2.1.2 块super_block 13
2.1.3 目录项dentry 14
2.1.4 索引节点inode 15
2.1.5 文件 17
2.2 文件系统的架构 17
2.2.1 块作用分析 17
2.2.2 dentry作用分析 18
2.2.3 inode作用分析 20
2.2.4 文件作用分析 21
2.3 从代码层次深入分析文件系统 21
2.3.1 一个单的文件系统aufs 22
2.3.2 文件系统如何管理目录和文件 26
2.3.3 文件系统的挂载过程 38
2.3.4 文件打开的代码分析 42
2.4 本章小结 59
第3章 设备的概念和总体架构 60
3.1 设备的配置表 60
3.2 访问设备寄存器和设备内存 61
3.3 设备中断和DMA 61
3.4 总线对设备的扫描 62
3.5 设备驱动管理 62
3.6 本章小结 62
第4章 为设备服务的特殊文件系统sysfs 63
4.1 文件和目录的创建 63
4.1.1 sysfs文件系统的初始化 64
4.1.2 sysfs文件系统目录的创建 64
4.1.3 普通文件的创建 68
4.2 sysfs文件的打开操作 69
4.2.1 real_lookup函数详解 70
4.2.2 为文件创建inode结构 70
4.2.3 为dentry结构绑定属性 71
4.2.4 调用文件系统中的open函数 72
4.3 sysfs文件的读写 74
4.3.1 读文件的过程分析 74
4.3.2 写文件的过程分析 75
4.4 kobject结构 76
4.4.1 kobject和kset的关系 76
4.4.2 kobject实例:总线的注册 77
4.5 本章小结 79
第5章 字符设备和input设备 80
5.1 文件如何变成设备 80
5.1.1 init_special_inode函数 80
5.1.2 def_chr_fops结构 81
5.2 input设备的注册 82
5.2.1 主从设备号 83
5.2.2 把input设备注册到系统 84
5.2.3 设备区间的登记 85
5.2.4 注册字符设备 86
5.2.5 打开input设备 87
5.3 input设备架构 88
5.3.1 注册input设备的驱动 88
5.3.2 匹配input管理的设备和驱动 89
5.3.3 注册input设备 90
5.4 本章小结 92
第6章 platform总线 93
6.1 从驱动发现设备的过程 93
6.1.1 驱动的初始化 93
6.1.2 注册驱动 94
6.1.3 为总线增加一个驱动 95
6.1.4 驱动加载 95
6.1.5 遍历总线上已经挂载的设备 96
6.2 从设备找到驱动的过程 98
6.2.1 注册设备和总线类型 98
6.2.2 注册设备的资源 99
6.2.3 增加一个设备对象 100
6.3 本章小结 102
第7章 serio总线 103
7.1 什么是总线适配器 103
7.2 向serio总线注册设备 103
7.2.1 注册端口登记事件 104
7.2.2 遍历总线的驱动 106
7.2.3 注册input设备 109
7.3 虚拟键盘驱动 110
7.3.1 键盘驱动的初始化 110
7.3.2 与设备建立连接 111
7.3.3 启动键盘设备 111
7.3.4 输入设备和主机系统之间的事件 112
7.4
摘要与插图
第1章内核的基础层和应用层
前言中提到,内核分为内核基础层和内核应用层。这既有对整个操作系统软件架构的分析和理解,也有现实应用情况的支持。
操作系统对应用软件提供了统一的编程接口,操作系统的系统调用是稳定的、向下兼容的,但是在内核中,并不提供这种稳定且兼容的保证。实际上,同样的代码在不同的内核版本经常可能编译失败。内核的这种开发模式,造成了学习内核时版本众多而且不稳定的特点,也大大增加了学习的困难。
在长期对内核代码的分析和应用中,笔者注意到一个事实:内核中提供了大量的软件基础设施。这些基础设施既包括内核中对内存的使用,对进程调度的控制,也包括自旋锁、信号量等内核提供的同步函数,同时还包括内核提供的数据结构,比如链表、hash链表、红黑树等。这些软件基础设施如同操作系统提供的系统调用一样,是理解内核代码和编写内核代码的基础。而这些软件基础设施在各个内核版本中基本是稳定的。
现实情况提供了另一方面的支持。学习的动力来自于应用,传统的操作系统教科书全面,但也很少有人能读懂并且结合代码进行实战应用。大多数程序员在工作中应用到内核的部分,绝大多数是设备驱动,而讲操作系统的书多数不会关注到设备驱动层面。除了设备驱动之外,内核中文件系统也有较多的应用。
要做到快速流畅地阅读内核代码,前提是了解内核中的软件基础设施。这些知识使用范围很广,分布在内核代码的各个部分,如果不了解,在内核代码的理解上就容易出现障碍。