这里列一下我看过的书籍的详细目录,方便搜索。
各位朋友可以点击这里从百度网盘下载pdf电子书。电子书请仅作为学习用途,有需要的话建议购买纸质书。
译者序
序言
前言
作者简介
第1章 Linux内核简介1
1.1 Unix的历史1
1.2 追寻Linus足迹: Linux简介2
1.3 操作系统和内核简介3
1.4 Linux内核和传统Unix内核的比较5
1.5 Linux内核版本7
1.6 Linux内核开发者社区8
1.7 小结8
第2章 从内核出发10
2.1 获取内核源码10
2.1.1 使用Git10
2.1.1 安装内核源代码10
2.1.3 使用补丁11
2.2 内核源码树11
2.3 编译内核12
2.3.1 配置内核12
2.3.2 减少编译的垃圾信息14
2.3.3 衍生多个编译作业 14
2.3.4 安装新内核14
2.4 内核开发的特点15
2.4.1 无libc库抑或无标准头文件15
2.4.2 GNU C16
2.4.3 没有内存保护机制18
2.4.4 不要轻易在内核中使用浮点数18
2.4.5 容积小而固定的栈18
2.4.6 同步和并发18
2.4.7 可移植性的重要性19
2.5 小结19
第3章 进程管理20
3.1 进程20
3.2 进程描述符及任务结构 21
3.2.1 分配进程描述符22
3.2.2 进程描述符的存放23
3.2.3 进程状态23
3.2.4 设置当前进程状态25
3.2.5 进程上下文25
3.2.6 进程家族树25
3.3 进程创建26
3.3.1 写时拷贝27
3.3.2 fork( )27
3.3.3 vfork( )28
3.4 线程在Linux中的实现28
3.4.1 创建线程29
3.4.2 内核线程30
3.5 进程终结31
3.5.1 删除进程描述符32
3.5.2 孤儿进程造成的进退维谷32
3.6 小结34
第4章 进程调度35
4.1 多任务35
4.2 Linux 的进程调度36
4.3 策略36
4.3.1 I/O消耗型和处理器消耗型的进程36
4.3.2 进程优先级37
4.3.3 时间片38
4.3.4 调度策略的活动38
4.4 Linux调度算法39
4.4.1 调度器类39
4.4.2 Unix 系统中的进程调度40
4.4.3 公平调度41
4.5 Linux调度的实现42
4.5.1 时间记账42
4.5.2 进程选择44
4.5.3 调度器入口48
4.5.4 睡眠和唤醒49
4.6 抢占和上下文切换51
4.6.1 用户抢占53
4.6.2 内核抢占53
4.7 实时调度策略54
4.8 与调度相关的系统调用54
4.8.1 与调度策略和优先级相关的系统调用55
4.8.2 与处理器绑定有关的系统调用55
4.8.3 放弃处理器时间56
4.9 小结56
第5章 系统调用57
5.1 与内核通信57
5.2 API、POSIX和C库57
5.3 系统调用58
5.3.1 系统调用号59
5.3.2 系统调用的性能59
5.4 系统调用处理程序60
5.4.1 指定恰当的系统调用60
5.4.2 参数传递60
5.5 系统调用的实现61
5.5.1 实现系统调用61
5.5.2 参数验证62
5.6 系统调用上下文64
5.6.1 绑定一个系统调用的最后步骤65
5.6.2 从用户空间访问系统调用67
5.6.3 为什么不通过系统调用的方式实现68
5.7 小结68
第6章 内核数据结构69
6.1 链表69
6.1.1 单向链表和双向链表69
6.1.2 环形链表70
6.1.3 沿链表移动71
6.1.4 Linux 内核中的实现71
6.1.5 操作链表73
6.1.6 遍历链表75
6.2 队列78
6.2.1 kfifo79
6.2.2 创建队列79
6.2.3 推入队列数据79
6.2.4 摘取队列数据80
6.2.5 获取队列长度80
6.2.6 重置和撤销队列80
6.2.7 队列使用举例 81
6.3 映射 81
6.3.1 初始化一个idr82
6.3.2 分配一个新的UID82
6.3.3 查找UID83
6.3.4 删除UID84
6.3.5 撤销idr84
6.4 二叉树84
6.4.1 二叉搜索树84
6.4.2 自平衡二叉搜索树 85
6.5 数据结构以及选择 87
6.6 算法复杂度88
6.6.1 算法88
6.6.2 大o 符号88
6.6.3 大θ符号89
6.6.4 时间复杂度89
6.7 小结 90
第7章 中断和中断处理91
7.1 中断91
7.2 中断处理程序92
7.3 上半部与下半部的对比93
7.4 注册中断处理程序93
7.4.1 中断处理程序标志94
7.4.2 一个中断例子95
7.4.3 释放中断处理程序95
7.5 编写中断处理程序96
7.5.1 共享的中断处理程序97
7.5.2 中断处理程序实例97
7.6 中断上下文99
7.7 中断处理机制的实现100
7.8 /proc/interrupts102
7.9 中断控制103
7.9.1 禁止和激活中断103
7.9.2 禁止指定中断线105
7.9.3 中断系统的状态105
7.10 小结106
第8章 下半部和推后执行的工作107
8.1 下半部107
8.1.1 为什么要用下半部108
8.1.2 下半部的环境108
8.2 软中断110
8.2.1 软中断的实现111
8.2.2 使用软中断113
8.3 tasklet114
8.3.1 tasklet的实现114
8.3.2 使用tasklet116
8.3.3 老的BH机制119
8.4 工作队列120
8.4.1 工作队列的实现121
8.4.2 使用工作队列124
8.4.3 老的任务队列机制126
8.5 下半部机制的选择127
8.6 在下半部之间加锁128
8.7 禁止下半部128
8.8 小结129
第9章 内核同步介绍131
9.1 临界区和竞争条件131
9.1.1 为什么我们需要保护132
9.1.2 单个变量133
9.2 加锁134
9.2.1 造成并发执行的原因135
9.2.2 了解要保护些什么136
9.3 死锁137
9.4 争用和扩展性138
9.5 小结140
第10章 内核同步方法141
10.1 原子操作141
10.1.1 原子整数操作142
10.1.2 64位原子操作144
10.1.3 原子位操作145
10.2 自旋锁147
10.2.1 自旋锁方法148
10.2.2 其他针对自旋锁的操作149
10.2.3 自旋锁和下半部150
10.3 读-写自旋锁150
10.4 信号量152
10.4.1 计数信号量和二值信号量153
10.4.2 创建和初始化信号量154
10.4.3 使用信号量154
10.5 读-写信号量155
10.6 互斥体156
10.6.1 信号量和互斥体158
10.6.2 自旋锁和互斥体158
10.7 完成变量158
10.8 BLK: 大内核锁159
10.9 顺序锁160
10.10 禁止抢占161
10.11 顺序和屏障162
10.12 小结165
第11章 定时器和时间管理166
11.1 内核中的时间概念166
11.2 节拍率: HZ167
11.2.1 理想的HZ值168
11.2.2 高HZ的优势169
11.2.3 高HZ的劣势169
11.3 jiffies170
11.3.1 jiffies的内部表示171
11.3.2 jiffies 的回绕172
11.3.3 用户空间和HZ173
11.4 硬时钟和定时器174
11.4.1 实时时钟174
11.4.2 系统定时器174
11.5 时钟中断处理程序174
11.6 实际时间176
11.7 定时器178
11.7.1 使用定时器178
11.7.2 定时器竞争条件180
11.7.3 实现定时器180
11.8 延迟执行181
11.8.1 忙等待181
11.8.2 短延迟182
11.8.3 schedule_timeout( )183
11.9 小结185
第12章 内存管理186
12.1 页186
12.2 区187
12.3 获得页189
12.3.1 获得填充为0的页190
12.3.2 释放页191
12.4 kmalloc( )191
12.4.1 gfp_mask标志192
12.4.2 kfree( )195
12.5 vmalloc( )196
12.6 slab层197
12.6.1 slab层的设计198
12.6.2 slab分配器的接口200
12.7 在栈上的静态分配203
12.7.1 单页内核栈203
12.7.2 在栈上光明正大地工作203
12.8 高端内存的映射204
12.8.1 永久映射204
12.8.2 临时映射204
12.9 每个CPU的分配205
12.10 新的每个CPU接口206
12.10.1 编译时的每个CPU数据206
12.10.2 运行时的每个CPU数据207
12.11 使用每个CPU数据的原因208
12.12 分配函数的选择209
12.13 小结209
第13章 虚拟文件系统210
13.1 通用文件系统接口210
13.2 文件系统抽象层211
13.3 Unix文件系统212
13.4 VFS 对象及其数据结构213
13.5 超级块对象214
13.6 超级块操作215
13.7 索引节点对象217
13.8 索引节点操作219
13.9 目录项对象222
13.9.1 目录项状态222
13.9.2 目录项缓存223
13.10 目录项操作224
13.11 文件对象225
13.12 文件操作226
13.13 和文件系统相关的数据结构230
13.14 和进程相关的数据结构232
13.15 小结233
第14章 块I/O层234
14.1 剖析一个块设备234
14.2 缓冲区和缓冲区头235
14.3 bio结构体237
14.3.1 I/O向量238
14.3.2 新老方法对比239
14.4 请求队列240
14.5 I/O调度程序240
14.5.1 I/O调度程序的工作241
14.5.2 Linus 电梯241
14.5.3 最终期限I/O调度程序242
14.5.4 预测I/O调度程序244
14.5.5 完全公正的排队I/O调度程序244
14.5.6 空操作的I/O调度程序245
14.5.7 I/O调度程序的选择245
14.6 小结246
第15章 进程地址空间247
15.1 地址空间247
15.2 内存描述符248
15.2.1 分配内存描述符249
15.2.2 撤销内存描述符250
15.2.3 mm_struct 与内核线程250
15.3 虚拟内存区域251
15.3.1 VMA标志251
15.3.2 VMA 操作253
15.3.3 内存区域的树型结构和内存区域的链表结构254
15.3.4 实际使用中的内存区域254
15.4 操作内存区域255
15.4.1 find_vma( )256
15.4.2 find_vma_prev( )257
15.4.3 find_vma_intersection( )257
15.5 mmap( )和do_mmap( ): 创建地址区间258
15.6 mummap( )和do_mummap( ): 删除地址区间259
15.7 页表260
15.8 小结261
第16章 页高速缓存和页回写262
16.1 缓存手段262
16.1.1 写缓存262
16.1.2 缓存回收263
16.2 Linux 页高速缓存264
16.2.1 address_space对象264
16.2.2 address_space 操作266
16.2.3 基树267
16.2.4 以前的页散列表268
16.3 缓冲区高速缓存268
16.4 flusher线程268
16.4.1 膝上型计算机模式270
16.4.2 历史上的bdflush、kupdated 和pdflush270
16.4.3 避免拥塞的方法: 使用多线程271
16.5 小结271
第17章 设备与模块273
17.1 设备类型273
17.2 模块274
17.2.1 Hello,World274
17.2.2 构建模块275
17.2.3 安装模块277
17.2.4 产生模块依赖性277
17.2.5 载入模块278
17.2.6 管理配置选项279
17.2.7 模块参数280
17.2.8 导出符号表282
17.3 设备模型283
17.3.1 kobject283
17.3.2 ktype284
17.3.3 kset285
17.3.4 kobject、ktype和kset的相互关系285
17.3.5 管理和操作kobject286
17.3.6 引用计数287
17.4 sysfs288
17.4.1 sysfs中添加和删除kobject 290
17.4.2 向sysfs中添加文件291
17.4.3 内核事件层293
17.5 小结294
第18章 调试295
18.1 准备开始295
18.2 内核中的bug296
18.3 通过打印来调试296
18.3.1 健壮性296
18.3.2 日志等级297
18.3.3 记录缓冲区298
18.3.4 syslogd和klogd298
18.3.5 从printf( )到printk( )的转换298
18.4 oops298
18.4.1 ksymoops300
18.4.2 kallsyms300
18.5 内核调试配置选项301
18.6 引发bug并打印信息301
18.7 神奇的系统请求键302
18.8 内核调试器的传奇303
18.8.1 gdb303
18.8.2 kgdb304
18.9 探测系统304
18.9.1 用UID作为选择条件304
18.9.2 使用条件变量305
18.9.3 使用统计量305
18.9.4 重复频率限制305
18.10 用二分查找法找出引发罪恶的变更306
18.11 使用Git进行二分搜索307
18.12 当所有的努力都失败时: 社区308
18.13 小结308
第19章 可移植性309
19.1 可移植操作系统309
19.2 Linux移植史310
19.3 字长和数据类型311
19.3.1 不透明类型313
19.3.2 指定数据类型314
19.3.3 长度明确的类型314
19.3.4 char型的符号问题315
19.4 数据对齐315
19.4.1 避免对齐引发的问题316
19.4.2 非标准类型的对齐316
19.4.3 结构体填补316
19.5 字节顺序318
19.6 时间319
19.7 页长度320
19.8 处理器排序320
19.9 SMP、内核抢占、高端内存321
19.10 小结321
第20章 补丁、开发和社区322
20.1 社区322
20.2 Linux编码风格322
20.2.1 缩进323
20.2.2 switch 语句323
20.2.3 空格324
20.2.4 花括号325
20.2.5 每行代码的长度326
20.2.6 命名规范326
20.2.7 函数326
20.2.8 注释326
20.2.9 typedef327
20.2.10 多用现成的东西328
20.2.11 在源码中减少使用ifdef328
20.2.12 结构初始化328
20.2.13 代码的事后修正329
20.3 管理系统329
20.4 提交错误报告329
20.5 补丁330
20.5.1 创建补丁330
20.5.2 用Git创建补丁331
20.5.3 提交补丁331
20.6 小结332
参考资料333
前言
第一章 绪论
Linux与其他类Unix内核的比较
硬件的依赖性
Linux版本
操作系统基本概念
Unix文件系统概述
Unix内核概述
第二章 内存寻址
内存地址
硬件中的分段
Linux中的分段
硬件中的分页
Linux中的分页
第三章 进程
进程、轻量级进程和线程
进程描述符
进程切换
创建进程
撤消进程
第四章 中断和异常
中断信号的作用
中断和异常
中断和异常处理程序的嵌套执行
初始化中断描述符表
异常处理
中断处理
软中断及tasklet
工作队列
从中断和异常返回
第五章 内核同步
内核如何为不同的请求提供服务
同步原语
对内核数据结构的同步访问
避免竞争条件的实例
第六章 定时测量
时钟和定时器电路
Linux计时体系结构
更新时间和日期
更新系统统计数
软定时器和延迟函数
与定时测量相关的系统调用
第七章 进程调度
调度策略
调度算法
调度程序所使用的数据结构
调度程序所使用的函数
多处理器系统中运行队列的平衡
与调度相关的系统调用
第八章 内存管理
页框管理
内存区管理
非连续内存区管理
第九章 进程地址空间
进程的地址空间
内存描述符
线性区
缺页异常处理程序
创建和删除进程的地址空间
堆的管理
第十章 系统调用
POSIX API和系统调用
系统调用处理程序及服务例程
进入和退出系统调用
参数传递
内核封装例程
第十一章 信号
信号的作用
产生信号
传递信号
与信号处理相关的系统调用
第十二章 虚拟文件系统
虚拟文件系统(VFS)的作用
VFS的数据结构
文件系统类型
文件系统处理
路径名查找
VFS系统调用的实现
文件加锁
第十三章 I/O体系结构和设备驱动程序
I/O体系结构
设备驱动程序模型
设备文件
设备驱动程序
字符设备驱动程序
第十四章 块设备驱动程序
块设备的处理
通用块层
I/O调度程序
块设备驱动程序
打开块设备文件
第十五章 页高速缓存
页高速缓存
把块存放在页高速缓存中
把脏页写入磁盘
sync()、fsync()和fdatasync()系统调用
第十六章 访问文件
读写文件
内存映射
直接I/O传送
异步I/O
第十七章 回收页框
页框回收算法
反向映射
PFRA实现
交换
第十八章 Ext2和Ext3文件系统
Ext2的一般特征
Ext2磁盘数据结构
Ext2的内存数据结构
创建Ext2文件系统
Ext2的方法
管理Ext2磁盘空间
Ext3文件系统
第十九章 进程通信
管道
FIFO
System V IPC
POSIX消息队列
第二十章 程序的执行
可执行文件
可执行格式
执行域
exec函数
附录一 系统启动
附录二 模块
参考文献
源代码索引
前言
第一章 设备驱动程序简介
设备驱动程序的作用
内核功能划分
设备和模块的分类
安全问题
版本编号
许可证条款
加入内核开发社团
本书概要
第二章 构造和运行模块
设置测试系统
Hello world模块
核心模块与应用程序的对比
编译和装载
内核符号表
预备知识
初始化和关闭
模块参数
在用户空间编写驱动程序
快速参考
第三章 字符设备驱动程序
scull的设计
主设备号和次设备号
一些重要的数据结构
字符设备的注册
open和release
scull的内存使用
read和write
试试新设备
快速参考
第四章 调试技术
内核中的调试支持
通过打印调试
通过查询调试
通过监视调试
调试系统故障
调试器和相关工具
第五章 并发和竞态
scull的缺陷
并发及其管理
信号量和互斥体
completiOn
自旋锁
锁陷阱
除了锁之外的办法
快速参考
第六章 高级字符驱动程序操作
ioctl
阻塞型I/O
poll和select
异步通知
定位设备
设备文件的访问控制
快速参考
第七章 时间、延迟及延缓操作
度量时间差
获取当前时间
延迟执行
内核定时器
tasklet
工作队列
快速参考
第八章 分配内存
kmalloc函数的内幕
后备高速缓存
get—free—page和相关函数
vmalloc及其辅助函数
per-CPU变量
获取大的缓冲区
快速参考
第九章 与硬件通信
I/O端口和I/O内存
使用I/O端口
I/O端口示例
使用I/O内存
快速参考
第十章 中断处理
准备并口
安装中断处理例程
实现中断处理例程
顶半部和底半部
中断共享
中断驱动的I/O
快速参考
第十一章 内核的数据类型
使用标准C语言类型
为数据项分配确定的空间大小
接口特定的类型
其他有关移植性的问题
链表
快速参考
第十二章 PCI驱动程序
PCI接口
ISA回顾
PC/104和PC/104+
其他的PC总线
SBus
NuBus
外部总线
快速参考
第十三章 USB驱动程序
USB设备基础
USB和Sysfs
USB urb
编写USB驱动程序
不使用urb的USB传输
快速参考
第十四章 Linux设备模型
kobject、kset和子系统
低层sysfs操作
热插拔事件的产生
总线、设备和驱动程序
类
各环节的整合
热插拔
处理固件
快速索引
第十五章 内存映射和DMA
Linux的内存管理
mmap设备操作
执行直接I/O访问
直接内存访问
快速参考
第十六章 块设备驱动程序
注册
块设备操作
请求处理
其他一些细节
快速参考
第十七章 网络驱动程序
snull设计
连接到内核
net_device结构细节
打开和关闭
数据包传输
数据包的接收
中断处理例程
不使用接收中断
链路状态的改变
套接字缓冲区
MAC 地址解析
定制 ioctl 命令
统计信息
组播
其他知识点详解
快速参考
第十八章 TTY驱动程序
小型TTY驱动程序
tty_driver函数指针
TTY线路设置
ioctls
proc和sysfs对TTY设备的处理
tty_driver结构详解
tty_operations结构详解
tty_struct结构详解
快速参考
参考书目
第1章 预备知识
1.1 Linux内核简介.
1.2 Intel X86 CPU系列的寻址方式
1.3 i386的页式内存管理机制
1.4 Linux内核源代码中的C语言代码
1.5 Linux内核源代码中的汇编语言代码
第2章 存储管理
2.1 Linux内存管理的基本框架
2.2 地址映射的全过程
2.3 几个重要的数据结构和函数
2.4 越界访问
2.5 用户堆栈的扩展
2.6 物理页面的使用和周转
2.7 物理页面的分配
2.8 页面的定期换出
2.9 页面的换入
2.10 内核缓冲区的管理
2.11 外部设备存储空间的地址映射
2.12 系统调用brk( )
2.13 系统调用mmap( )
第3章 中断、异常和系统调用
3.1 X86 CPU对中断的硬件支持
3.2 中断向量表IDT的初始化
3.3 中断请求队列的初始化
3.4 中断的响应和服务
3.5 软中断与Bottom Half
3.6 页面异常的进入和返回
3.7 时钟中断
3.8 系统调用
3.9 系统调用号与跳转表
第4章 进程与进程调度
4.1 进程四要素
4.2 进程三部曲: 创建、执行与消亡
4.3 系统调用fork( )、vfork( )与clone( )
4.4 系统调用execve( )
4.5 系统调用exit( )与wait4( )
4.6 进程的调度与切换
4.7 强制性调度
4.8 系统调用nanosleep( )和pause( )
4.9 内核中的互斥操作
第5章 文件系统
5.1 概述
5.2 从路径名到目标节点
5.3 访问权限与文件安全性
5.4 文件系统的安装和拆卸
5.5 文件的打开与关闭
5.6 文件的写与读
5.7 其他文件操作
5.8 特殊文件系统/proc
第6章 传统的Unix进程间通信
6.1 概述
6.2 管道和系统调用pipe( )
6.3 命名管道
6.4 信号
6.5 系统调用ptrace( )和进程跟踪
6.6 报文传递
6.7 共享内存
6.8 信号量
第7章 基于socket的进程间通信
第8章 设备驱动
第9章 多处理器SMP系统结构
第10章 系统引导与初始化
第1章 简介和概述
1.1 内核的任务
1.2 实现策略
1.3 内核组成部分
1.3.1 进程、进程切换、调度
1.3.2 UNIX进程
1.3.3 地址空间与特权级别
1.3.4 页表
1.3.5 物理内存的分配
1.3.6 计时
1.3.7 系统调用
1.3.8 设备驱动程序、块设备和字符设备
1.3.9 网络
1.3.10 文件系统
1.3.11 模块和热插拔
1.3.12 缓存
1.3.13 链表处理
1.3.14 对象管理和引用计数
1.3.15 数据类型
1.3.16 本书的局限性
1.4 为什么内核是特别的
第2章 进程管理和调度
2.1 进程优先级
2.2 进程生命周期
2.3 进程表示
2.3.1 进程类型
2.3.2 命名空间
2.3.3 进程ID号
2.3.4 进程关系
2.4 进程管理相关的系统调用
2.4.1 进程复制
2.4.2 内核线程
2.4.3 启动新程序
2.4.4 退出进程
2.5 调度器的实现
2.5.1 概观
2.5.2 数据结构
2.5.3 处理优先级
2.5.4 核心调度器
2.6 完全公平调度类
2.6.1 数据结构
2.6.2 CFS操作
2.6.3 队列操作
2.6.4 选择下一个进程
2.6.5 处理周期性调度器
2.6.6 唤醒抢占
2.6.7 处理新进程
2.7 实时调度类
2.7.1 性质
2.7.2 数据结构
2.7.3 调度器操作
2.8 调度器增强
2.8.1 SMP调度
2.8.2 调度域和控制组
2.8.3 内核抢占和低延迟相关工作
第3章 内存管理
3.1 概述
3.2 (N)UMA模型中的内存组织
3.2.1 概述
3.2.2 数据结构
3.3 页表
3.3.1 数据结构
3.3.2 页表项的创建和操作
3.4 初始化内存管理
3.4.1 建立数据结构
3.4.2 特定于体系结构的设置
3.4.3 启动过程期间的内存管理
3.5 物理内存的管理
3.5.1 伙伴系统的关系
3.5.2 避免碎片
3.5.3 初始化内存域和节点数据结构
3.5.4 分配器API
3.5.5 分配页
3.5.6 释放页
3.5.7 内核中不连续页的分配
3.5.8 内核映射
3.6 slab分配器
3.6.1 备选分配器
3.6.2 内核中的内存管理
3.6.3 slab分配的原理
3.6.4 实现
3.6.5 通用缓存
3.7 处理器高速缓存和TLB控制
第4章 进程虚拟内存
4.1 简介
4.2 进程虚拟地址空间
4.2.1 进程地址空间的布局
4.2.2 建立布局
4.3 内存映射的原理
4.4 数据结构
4.4.1 树和链表
4.4.2 虚拟内存区域的表示
4.4.3 优先查找树
4.5 对区域的操作
4.5.1 将虚拟地址关联到区域
4.5.2 区域合并
4.5.3 插入区域
4.5.4 创建区域
4.6 地址空间
4.7 内存映射
4.7.1 创建映射
4.7.2 删除映射
4.7.3 非线性映射
4.8 反向映射
4.8.1 数据结构
4.8.2 建立逆向映射
4.8.3 使用逆向映射
4.9 堆的管理
4.10 缺页异常的处理
4.11 用户空间缺页异常的校正
4.11.1 按需分配/调页
4.11.2 匿名页
4.11.3 写时复制
4.11.4 获取非线性映射
4.12 内核缺页异常
4.13 在内核和用户空间之间复制数据
第5章 锁与进程间通信
5.1 控制机制
5.1.1 竞态条件
5.1.2 临界区
5.2 内核锁机制
5.2.1 对整数的原子机制
5.2.2 自旋锁
5.2.3 信号量
5.2.4 RCU机制
5.2.5 内存和优化屏障
5.2.6 读者/写者锁
5.2.7 大内核锁
5.2.8 互斥量
5.2.9 近似的per-CPU计算器
5.2.10 锁竞争和细粒度锁
5.3 System V进程间通信
5.3.1 System V机制
5.3.2 信号量
5.3.3 消息队列
5.3.4 共享内存
5.4 其他IPC机制
5.4.1 信号
5.4.2 管道和套接字
第6章 设备驱动程序
6.1 I/O体系结构
6.2 访问设备
6.2.1 设备文件
6.2.2 字符设备、块设备和其他设备
6.2.3 使用ioctl进行设备寻址
6.2.4 主从设备号的表示
6.2.5 注册
6.3 与文件系统关联
6.3.1 inode中的设备文件成员
6.3.2 标准文件操作
6.3.3 用于字符设备的标准操作
6.3.4 用户块设备的标准操作
6.4 字符设备操作
6.4.1 表示字符设备
6.4.2 打开设备文件
6.4.3 读写操作
6.5 块设备操作
6.5.1 块设备的表示
6.5.2 数据结构
6.5.3 向系统添加磁盘和分区
6.5.4 打开块设备文件
6.5.5 请求结构
6.5.6 BIO
6.5.7 请求提交
6.5.8 I/O调度
6.5.9 ioctl的实现
6.6 资源分配
6.6.1 资源管理
6.6.2 I/O内存
6.6.3 I/O端口
6.7 总线系统
6.7.1 通用驱动程序模型
6.7.2 PCI总线
6.7.3 USB
第7章 模块
7.1 概述
7.2 使用模块
7.2.1 添加和移除
7.2.2 依赖关系
7.2.3 查询模块信息
7.2.4 自动加载
7.3 插入和删除模块
7.3.1 模块的表示
7.3.2 依赖关系和引用
7.3.3 模块的二进制结构
7.3.4 插入模块
7.3.5 移除模块
7.4 自动化与热插拔
7.4.1 kmod实现的自动加载
7.4.2 热插拔
7.5 版本控制
7.5.1 校验和方法
7.5.2 版本控制函数
第8章 虚拟文件系统
8.1 文件系统类型
8.2 通用文件类型
8.2.1 inode
8.2.2 链接
8.2.3 编程接口
8.2.4 将文件作为通用接口
8.3 VFS的结构
8.3.1 结构概观
8.3.2 inode
8.3.3 特定于进程的信息
8.3.4 文件操作
8.3.5 目录项缓存
8.4 处理VFS对象
8.4.1 文件系统操作
8.4.2 文件操作
8.5 标准函数
8.5.1 通用读取例程
8.5.2 失效机制
8.5.3 权限检查
8.6 小结
第9章 Ext文件系统族
9.1 简介
9.2 Ext2文件系统
9.2.1 物理结构
9.2.2 数据结构
9.2.3 创建文件系统
9.2.4 文件系统操作
9.3 Ext3文件系统
9.3.1 概念
9.3.2 数据结构
9.4 小结
第10章 无持久存储的文件系统
10.1 Proc文件系统
10.1.1 /proc的内容
10.1.2 数据结构
10.1.3 初始化
10.1.4 装载proc文件系统
10.1.5 管理/proc数据项
10.1.6 读取和写入信息
10.1.7 进程相关的信息
10.1.8 系统控制机制
10.2 简单的文件系统
10.2.1 顺序文件
10.2.2 用libfs编写文件系统
10.2.3 调试文件系统
10.2.4 伪文件系统
10.3 sysfs
10.3.1 概述
10.3.2 数据结构
10.3.3 装载文件系统
10.3.4 文件和目录操作
10.3.5 向sysfs添加内容
10.4 小结
第11章 扩展属性和访问控制表
11.1 扩展属性
11.1.1 到虚拟文件系统的接口
11.1.2 Ext3中的实现
11.1.3 Ext2中的实现
11.2 访问控制表
11.2.1 通用实现
11.2.2 Ext3中的实现
11.2.3 Ext2中的实现
第12章 网络
12.1 互联的计算机
12.2 ISO/OSI和TCP/IP参考模型
12.3 通过套接字通信
12.3.1 创建套接字
12.3.2 使用套接字
12.3.3 数据报套接字
12.4 网络实现的分层模型
12.5 网络命名空间
12.6 套接字缓冲区
12.6.1 使用套接字缓冲区管理数据
12.6.2 管理套接字缓冲区数据
12.7 网络访问层
12.7.1 网络设备的表示
12.7.2 接受分组
12.7.3 发送分组
12.8 网络层
12.8.1 IPv4
12.8.2 接收分组
12.8.3 交付到本地传输层
12.8.4 分组转发
12.8.5 发送分组
12.8.6 netfilter
12.8.7 IPv6
12.9 传输层
12.9.1 UDP
12.9.2 TCP
12.10 应用层
12.10.1 socket数据结构
12.10.2 套接字和文件
12.10.3 socketcall系统调用
12.10.4 创建套接字
12.10.5 接受数据
12.10.6 接收数据
12.10.7 发送数据
12.11 内核内部的网络通信
12.11.1 通信函数
12.11.2 netlink机制
第13章 系统调用
13.1 系统程序设计基础
13.1.1 追踪系统调用
13.1.2 支持的标准
13.1.3 重启系统调用
13.2 可用的系统调用
13.3 系统调用的实现
13.3.1 系统调用的结构
13.3.2 访问用户空间
13.3.3 追踪系统调用
第14章 内核活动
14.1 中断
14.1.1 中断类型
14.1.2 硬件IRQ
14.1.3 处理中断
14.1.4 数据结构
14.1.5 中断电流处理
14.1.6 初始化和分配IRQ
14.1.7 处理IRQ
14.2 软中断
14.2.1 开启软中断处理
14.2.2 软中断守护进程
14.3 tasklet
14.3.1 创建tasklet
13.3.2 注册tasklet
14.3.3 执行tasklet
14.4 等待队列和完成量
14.4.1 等待队列
14.4.2 完成量
14.4.3 工作队列
第15章 时间管理
15.1 概述
15.1.1 定时器的类型
15.1.2 配置选项
15.2 低分辨率定时器的实现
15.2.1 定时器激活与进程统计
15.2.2 处理jiffies
15.2.3 数据结构
15.2.4 动态定时器
15.3 通用时间子系统
15.3.1 概述
15.3.2 配置选项
15.3.3 时间表示
15.3.4 用于时间管理的对象
15.4 高分辨率定时器
15.4.1 数据结构
15.4.2 设置定时器
15.4.3 实现
15.4.4 周期时钟仿真
15.4.5 切换到高分辨率定时器
15.5 动态时钟
15.5.1 数据结构
15.5.2 低分辨率系统下的动态时钟
15.5.3 高分辨率系统下的动态时钟
15.5.4 停止和启动周期时钟
15.6 广播模式
15.7 定时器相关系统调用的实现
15.7.1 时间基准
15.7.2 alarm和setitimer系统调用
15.7.3 获取当前时间
15.8 管理进程时间
第16章 页缓存和块缓存
16.1 页缓存的结构
16.1.1 管理和查找缓存的页
16.1.2 回写修改的数据
16.2 块存储的结构
16.3 地址空间
16.3.1 数据结构
16.3.2 页树
16.3.3 地址空间操作
16.4 页缓存的实现
16.4.1 分配页
16.4.2 查找页
16.4.3 在页上等待
16.4.4 对整页的操作
16.4.5 页缓存预读
16.5 块缓存的实现
16.5.1 数据结构
16.5.2 操作
16.5.3 页缓存和块缓存的交互
16.5.4 对立的缓存区
第17章 数据同步
17.1 概述
17.2 pdflush机制
17.3 启动新线程
17.4 线程初始化
17.5 执行实际工作
17.6 周期性刷出
17.7 相关的数据结构
17.7.1 页状态
17.7.2 回写控制
17.7.3 可调参数
17.8 中央控制
17.9 超级块同步
17.10 inode同步
17.10.1 遍历超级块
17.10.2 考察超级块inode
17.10.3 回写单个inode
17.11 拥塞
17.11.1 数据结构
17.11.2 阈值
17.11.3 拥塞状态的设置和消除
17.11.4 在拥塞队列上等待
17.12 强制回写
17.13 膝上模式
17.14 用于同步控制的系统调用
17.15 完全同步
17.15.1 inode的同步
17.15.2 单个文件的同步
17.15.3 内存映射的同步
第18章 页面回收和页交换
18.1 概述
18.1.1 可换出页
18.1.2 页颠簸
18.1.3 页交换算法
18.2 Linux内核中的页面回收和页交换
18.2.1 交换区的组织
18.2.2 检查内存使用情况
18.2.3 选择要换出的页
18.2.4 处理缺页异常
18.2.5 缩减内核缓存
18.3 管理交换区
18.3.1 数据结构
18.3.2 创建交换区
18.3.3 激活交换区
18.4 交换缓存
18.4.1 标识换出页
18.4.2 交换缓存的结构
18.4.3 添加新页
18.4.4 搜索一页
18.5 数据回写
18.6 页面回收
18.6.1 概述
18.6.2 数据结构
18.6.3 确定页的活动程度
18.6.4 收缩内存域
18.6.5 隔离LRU页和集中回收
18.6.6 收缩活动页链表
18.6.7 回收不活动页
18.7 交换令牌
18.8 处理交换缺页异常
18.8.1 换入页
18.8.2 读取数据
18.8.3 交换预读
18.9 发起内存回收
18.9.1 用kswapd进行周期性内存回收
18.9.2 在严重内存不足时换出页
18.10 收缩其他缓存
18.10.1 数据结构
18.10.2 注册和删除收缩器
18.10.3 收缩缓存
第19章 审计
19.1 概述
19.2 审计规则
19.3 实现
19.3.1 数据结构
19.3.2 初始化
19.3.3 处理请求
19.3.4 记录事件
19.3.5 系统调用审计
附录A 体系结构相关知识
附录B 使用源代码
附录C 有关C语言的注记附录D 系统启动
附录E ELF二进制格式
附录F 内核开发过程参考文献
第1章 概述
1.1 Linux的诞生和发展
1.1.1 UNIX操作系统的诞生
1.1.2 MINIX操作系统
1.1.3 GNU计划
1.1.4 POSIX标准
1.1.5 Linux操作系统的诞生
1.1.6 Linux操作系统版本的变迁
1.1.7 Linux名称的由来
1.1.8 早期Linux系统开发的主要贡献者
1.2 内容综述
1.3 本章小结
第2章 微型计算机组成结构
2.1 微型计算机组成原理
2.2 I/O端口寻址和访问控制方式
2.2.1 I/O端口和寻址
2.2.2 接口访问控制
2.3 主存储器、BIOS和CMOS存储器
2.3.1 主存储器
2.3.2 基本输入/输出程序BIOS
2.3.3 CMOS存储器
2.4 控制器和控制卡
2.4.1 中断控制器
2.4.2 DMA控制器
2.4.3 定时/计数器
2.4.4 键盘控制器
2.4.5 串行控制卡
2.4.6 显示控制
2.4.7 软盘和硬盘控制器
2.5 本章小结
第3章 内核编程语言和环境
3.1 as86汇编器
3.1.1 as86汇编语言语法
3.1.2 as86汇编语言程序
3.1.3 as86汇编语言程序的编译和链接
3.1.4 as86和1d86使用方法和选项
3.2 CNU as汇编
3.2.1 编译as汇编语言程序
3.2.2 as汇编语法
3.2.3 指令语句、操作数和寻址
3.2.4 区与重定位
3.2.5 符号
3.2.6 as汇编命令
3.2.7 编写16位代码
3.2.8 AS汇编器命令行选项
3.3 C语言程序
3.3.1 C程序编译和链接
3.3.2 嵌入汇编
3.3.3 圆括号中的组合语句
3.3.4 寄存器变量
3.3.5 内联函数
3.4 C与汇编程序的相互调用
3.4.1 C函数调用机制
3.4.2 在汇编程序中调用C函数
3.4.3 在C程序中调用汇编函数
3.5 Linux 0.12目标文件格式
3.5.1 目标文件格式
3.5.2 Linux0.12中的目标文件格式
3.5.3 链接程序输出
3.5.4 链接程序预定义变量一
3.5.5 System.map文件
3.6 Make程序和Makefile文件
3.6.1 Makefite文件内容
3.6.2 Makefile文件中的规则
3.6.3 Makefile文件示例
3.6.4 make处理Makefile文件的方式
3.6.5 Makefile中的变量
3.6.6 让make自动推断命令
3.6.7 隐含规则中的自动变量
3.7本章 小结
第4章 80x86保护模式及其编程
4.1 80x86系统寄存器和系统指令
4.1.1 标志寄存器
4.1.2 内存管理寄存器
4.1.3 控制寄存器
4.1.4 系统指令
4.2 保护模式内存管理
4.2.1 内存寻址
4.2.2 地址变换
4.2.3 保护
4.3 分段机制
4.3.1 段的定义
4.3.2 段描述符表
4.3.3 段选择符
4.3.4 段描述符
4.3.5 代码和数据段描述符类型
4.3.6 系统描述符类型
4.4 分页机制
4.4.1 页表结构
4.4.2 页表项格式
4.4.3 虚拟存储
4.5 保护
4.5.1 段级保护
4.5.2 访问数据段时的特权级检查
4.5.3 代码段之间转移控制时的特权级检查
4.5.4 页级保护
4.5.5 组合页级和段级保护
4.6 中断和异常处理
4.6.1 异常和中断向量
4.6.2 中断源和异常源
4.6.3 异常分类
4.6.4 程序或任务的重新执行
4.6.5 开启和禁止中断
4.6.6 异常和中断的优先级
4.6.7 中断描述符表
4.6.8 IDT描述符
4.6.9 异常与中断处理
4.6.10 中断处理任务
4.6.11 错误码
4.7 任务管理
4.7.1 任务的结构和状态
4.7.2 任务的执行
4.7.3 任务管理数据结构
4.7.4 任务切换
4.7.5 任务链
4.7.6 任务地址空间
4.8 保护模式编程初始化
4.8.1 进入保护模式时的初始化操作
4.8.2 模式切换
4.9 一个简单的多任务内核实例
4.9.1 多任务程序结构和工作原理
4.9.2 引导启动程序boot.s
4.9.3 多任务内核程序head.s
第5章 Linux内核体系结构
5.1 Linux内核模式
5.2 Linux内核系统体系结构
5.3 Linux内核对内存的管理和使用
5.3.1 物理内存
5.3.2 内存地址空间概念
5.3.3 内存分段机制
5.3.4 内存分页管理
5.3.5 CPu多任务和保护方式
5.3.6 虚拟地址、线性地址和物理地址之间的关系
5.3.7 用户申请内存的动态分配
5.4 中断机制
5.4.1 中断操作原理
5.4.2 80x86微机的中断子系统
5.4.3 中断向量表
5.4.4 I.inux内核的中断处理
5.4.5 标志寄存器的中断标志
5.5 Linux的系统调用
5.5.1 系统调用接口
5.5.2 系统调用处理过程
5.5.3 Linux系统调用的参数传递方式
5.6 系统时间和定时
5.6.1 系统时间
5.6.2 系统定时
5.7 Linux进程控制
5.7.1 任务数据结构
5.7.2 进程运行状态
5.7.3 进程初始化
5.7.4 创建新进程
5.7.5 进程调度
5.7.6 终止进程
5.8 Linux系统中堆栈的使用方法
5.8.1 初始化阶段
5.8.2 任务的堆栈
5.8.3 任务内核态堆栈与用户态堆栈之间的切换
5.9 Linux0.12采用的文件系统
5.10 Linux内核源代码的目录结构
5.10.1 内核主目录linux
5.10.2 引导启动程序目录boot
5.10.3 文件系统目录fs
5.10.4 头文件主目录include
5.10.5 内核初始化程序目录init
5.10.6 内核程序主目录kernel
5.10.7 内核库函数目录lib
5.10.8 内存管理程序目录mm
5.10.9 编译内核工具程序目录tools
5.11 内核系统与应用程序的关系
5.12 linux/MakeftIe文件
5.12.1 功能描述
5.12.2 代码注释
5.13 本章 小结
第6章 引导启动程序
6.1 总体功能
6.2 bootsect.S程序
6.2.1 功能描述
6.2.2 代码注释
6.2.3 其他信息
6.3 setup.S程序
6.3.1 功能描述
6.3.2 代码注释
6.3.3 其他信息
6.4 lead.s程序
6.4.1 功能描述
6.4.2 代码注释
6.4.3 其他信息
6.5 本章 小结
第7章 初始化程序
7.1 main.c程序
7.1.1 功能描述
7.1.2 代码注释
7.1.3 其他信息
7.2 环境初始化工作
7.3 本章 小结
第8章 内核代码
8.1 总体功能
8.1.1 中断处理程序
8.1.2 系统调用处理相关程序
8.1.3 其他通用类程序
8.2 asm.s程序
8.2.1 功能描述
8.2.2 代码注释
8.2.3 Intel保留中断向量的定义
8.3 traps.c程序
8.3.1 功能描述
8.3.2 代码注释
8.4 syscall.s程序
8.4.1 功能描述
8.4.2 代码注释
8.4.3 其他信息
8.5 mktime.c程序
8.5.1 功能描述
8.5.2 代码注释
8.5.3 闰年的计算方法
8.6 sched.c程序
8.6.1 功能描述
8.6.2 代码注释
8.6.3 其他信息
8.7 signal.c程序
8.7.1 功能描述
8.7.2 代码注释
8.7.3 进程信号说明
8.8 exit.c程序
8.8.1 功能描述
8.8.2 代码注释
8.9 fork.c程序
8.9.1 功能描述
8.9.2 代码注释
8.9.3 任务状态段信息
8.10 sys.c程序
8.10.1 功能描述
8.10.2 代码注释
8.1l vsprimtfc程序
8.11.1 功能描述
8.11.2 代码注释
8.11.3 vsprintf的格式字符串
8.11.4 与当前版本的区别
8.12 printk.c程序
8.12.1 功能描述
8.12.2 代码注释
8.13 panic.c程序
8.13.1 功能描述
8.13.2 代码注释
8.14 本章 小结
第9章 块设备驱动程序
9.1 总体功能
9.1.1 块设备请求项和请求队列
9.1.2 块设备访问调度处理
9.1.3 块设备操作方式
9.2 blk.h文件
9.2.1 功能描述
9.2.2 代码注释
9.3 hd.c程序
9.3.1 功能描述
9.3.2 代码注释
9.3.3 其他信息
9.4 nrwblk.c程序
9.4.1 功能描述
9.4.2 代码注释
9.5 ramdisk.c程序
9.5.1 功能描述
9.5.2 代码注释
9.6 floppy.c程序
9.6.1 功能描述
9.6.2 代码注释
9.6.3 其他信息
第10章 字符设备驱动程序
10.1 总体功能
10.1.1 终端驱动程序基本原理
10.1.2 Linux支持的终端设备类型
10.1.3 终端基本数据结构
lO.1.4 规范模式和非规范模式
10.1.5 控制台终端和串行终端设备
10.1.6 终端驱动程序接口
10.2 keyboard.S程序
10.2.1 功能描述
10.2.2 代码注释
10.2.3 其他信息
10.3 console.c程序
10.3.1 功能描述
10.3.2 代码注释
10.3.3 其他信息
10.4 serial.c程序
10.4.l 功能描述
10.4.2 代码注释
lO.4.3 异步串行通信控制器UART
10.5 rsio.s程序
10.5.1 功能描述
10.5.2 代码注释
10.6 ttyi0.c程序
10.6.1 功能描述
10.6.2 代码注释
10.6.3 控制字符vnME、VMlN
10.7 ttyjoctl.c程序
10.7.1 功能描述
10.7.2 代码注释
第11章 数学协处理器
第12章 文件系统
第13章 内存管理
第14章 头文件
第15章 库文件
第16章 建造工具
第17章 实验环境设置与使用方法
附录
参考文献
赞誉
推荐序一
推荐序二
前言
第1章 Linux设备驱动概述及开发环境构建 1
1.1 设备驱动的作用 1
1.2 无操作系统时的设备驱动 2
1.3 有操作系统时的设备驱动 4
1.4 Linux设备驱动 5
1.4.1 设备的分类及特点 5
1.4.2 Linux设备驱动与整个软硬件系统的关系 6
1.4.3 Linux设备驱动的重点、难点 7
1.5 Linux设备驱动的开发环境构建 8
1.5.1 PC上的Linux环境 8
1.5.2 QEMU实验平台 11
1.5.3 源代码阅读和编辑 13
1.6 设备驱动Hello World: LED驱动 15
1.6.1 无操作系统时的LED驱动 15
1.6.2 Linux下的LED驱动 15
第2章 驱动设计的硬件基础 20
2.1 处理器 20
2.1.1 通用处理器 20
2.1.2 数字信号处理器 22
2.2 存储器 24
2.3 接口与总线 28
2.3.1 串口 28
2.3.2 I2C 29
2.3.3 SPI 30
2.3.4 USB 31
2.3.5 以太网接口 33
2.3.6 PCI和PCI-E 34
2.3.7 SD和SDIO 36
2.4 CPLD和FPGA 37
2.5 原理图分析 40
2.6 硬件时序分析 42
2.6.1 时序分析的概念 42
2.6.2 典型的硬件时序 43
2.7 芯片数据手册阅读方法 44
2.8 仪器仪表使用 47
2.8.1 万用表 47
2.8.2 示波器 47
2.8.3 逻辑分析仪 49
2.9 总结 51
第3章 Linux内核及内核编程 52
3.1 Linux内核的发展与演变 52
3.2 Linux 2.6后的内核特点 56
3.3 Linux内核的组成 59
3.3.1 Linux内核源代码的目录结构 59
3.3.2 Linux内核的组成部分 60
3.3.3 Linux内核空间与用户空间 64
3.4 Linux内核的编译及加载 64
3.4.1 Linux内核的编译 64
3.4.2 Kconfig和Makefile 66
3.4.3 Linux内核的引导 74
3.5 Linux下的C编程特点 75
3.5.1 Linux编码风格 75
3.5.2 GNU C与ANSI C 78
3.5.3 do { } while(0) 语句 83
3.5.4 goto语句 85
3.6 工具链 85
3.7 实验室建设 88
3.8 串口工具 89
3.9 总结 91
第4章 Linux内核模块 92
4.1 Linux内核模块简介 92
4.2 Linux内核模块程序结构 95
4.3 模块加载函数 95
4.4 模块卸载函数 97
4.5 模块参数 97
4.6 导出符号 99
4.7 模块声明与描述 100
4.8 模块的使用计数 100
4.9 模块的编译 101
4.10 使用模块“绕开”GPL 102
4.11 总结 103
第5章 Linux文件系统与设备文件 104
5.1 Linux文件操作 104
5.1.1 文件操作系统调用 104
5.1.2 C库文件操作 108
5.2 Linux文件系统 109
5.2.1 Linux文件系统目录结构 109
5.2.2 Linux文件系统与设备驱动 110
5.3 devfs 114
5.4 udev用户空间设备管理 116
5.4.1 udev与devfs的区别 116
5.4.2 sysfs文件系统与Linux设备模型 119
5.4.3 udev的组成 128
5.4.4 udev规则文件 129
5.5 总结 133
第6章 字符设备驱动 134
6.1 Linux字符设备驱动结构 134
6.1.1 cdev结构体 134
6.1.2 分配和释放设备号 136
6.1.3 file_operations结构体 136
6.1.4 Linux字符设备驱动的组成 138
6.2 globalmem虚拟设备实例描述 142
6.3 globalmem设备驱动 142
6.3.1 头文件、宏及设备结构体 142
6.3.2 加载与卸载设备驱动 143
6.3.3 读写函数 144
6.3.4 seek函数 146
6.3.5 ioctl函数 146
6.3.6 使用文件私有数据 148
6.4 globalmem驱动在用户空间中的验证 156
6.5 总结 157
第7章 Linux设备驱动中的并发控制 158
7.1 并发与竞态 158
7.2 编译乱序和执行乱序 160
7.3 中断屏蔽 165
7.4 原子操作 166
7.4.1 整型原子操作 167
7.4.2 位原子操作 168
7.5 自旋锁 169
7.5.1 自旋锁的使用 169
7.5.2 读写自旋锁 173
7.5.3 顺序锁 174
7.5.4 读-复制-更新 176
7.6 信号量 181
7.7 互斥体 183
7.8 完成量 184
7.9 增加并发控制后的globalmem的设备驱动 185
7.10 总结 188
第8章 Linux设备驱动中的阻塞与非阻塞I/O 189
8.1 阻塞与非阻塞I/O 189
8.1.1 等待队列 191
8.1.2 支持阻塞操作的globalfifo设备驱动 194
8.1.3 在用户空间验证globalfifo的读写 198
8.2 轮询操作 198
8.2.1 轮询的概念与作用 198
8.2.2 应用程序中的轮询编程 199
8.2.3 设备驱动中的轮询编程 201
8.3 支持轮询操作的globalfifo驱动 202
8.3.1 在globalfifo驱动中增加轮询操作 202
8.3.2 在用户空间中验证globalfifo设备的轮询 203
8.4 总结 205
第9章 Linux设备驱动中的异步通知与异步I/O 206
9.1 异步通知的概念与作用 206
9.2 Linux异步通知编程 207
9.2.1 Linux信号 207
9.2.2 信号的接收 208
9.2.3 信号的释放 210
9.3 支持异步通知的globalfifo驱动 212
9.3.1 在globalfifo驱动中增加异步通知 212
9.3.2 在用户空间中验证globalfifo的异步通知 214
9.4 Linux异步I/O 215
9.4.1 AIO概念与GNU C库AIO 215
9.4.2 Linux内核AIO与libaio 219
9.4.3 AIO与设备驱动 222
9.5 总结 223
第10章 中断与时钟 224
10.1 中断与定时器 224
10.2 Linux中断处理程序架构 227
10.3 Linux中断编程 228
10.3.1 申请和释放中断 228
10.3.2 使能和屏蔽中断 230
10.3.3 底半部机制 230
10.3.4 实例: GPIO按键的中断 235
10.4 中断共享 237
10.5 内核定时器 238
10.5.1 内核定时器编程 238
10.5.2 内核中延迟的工作delayed_work 242
10.5.3 实例: 秒字符设备 243
10.6 内核延时 247
10.6.1 短延迟 247
10.6.2 长延迟 248
10.6.3 睡着延迟 248
10.7 总结 250
第11章 内存与I/O访问 251
11.1 CPU与内存、I/O 251
11.1.1 内存空间与I/O空间 251
11.1.2 内存管理单元 252
11.2 Linux内存管理 256
11.3 内存存取 261
11.3.1 用户空间内存动态申请 261
11.3.2 内核空间内存动态申请 262
11.4 设备I/O端口和I/O内存的访问 267
11.4.1 Linux I/O端口和I/O内存访问接口 267
11.4.2 申请与释放设备的I/O端口和I/O内存 268
11.4.3 设备I/O端口和I/O内存访问流程 269
11.4.4 将设备地址映射到用户空间 270
11.5 I/O内存静态映射 276
11.6 DMA 277
11.6.1 DMA与Cache一致性 278
11.6.2 Linux下的DMA编程 279
11.7 总结 285
第12章 Linux设备驱动的软件架构思想 286
12.1 Linux驱动的软件架构 286
12.2 platform设备驱动 290
12.2.1 platform总线、设备与驱动 290
12.2.2 将globalfifo作为platform设备 293
12.2.3 platform设备资源和数据 295
12.3 设备驱动的分层思想 299
12.3.1 设备驱动核心层和例化 299
12.3.2 输入设备驱动 301
12.3.3 RTC设备驱动 306
12.3.4 Framebuffer设备驱动 309
12.3.5 终端设备驱动 311
12.3.6 misc设备驱动 316
12.3.7 驱动核心层 321
12.4 主机驱动与外设驱动分离的设计思想 321
12.4.1 主机驱动与外设驱动分离 321
12.4.2 Linux SPI主机和设备驱动 322
12.5 总结 330
第13章 Linux块设备驱动 331
13.1 块设备的I/O操作特点 331
13.2 Linux块设备驱动结构 332
13.2.1 block_device_operations结构体 332
13.2.2 gendisk结构体 334
13.2.3 bio、request和request_queue 335
13.2.4 I/O调度器 339
13.3 Linux块设备驱动的初始化 340
13.4 块设备的打开与释放 342
13.5 块设备驱动的ioctl函数 342
13.6 块设备驱动的I/O请求处理 343
13.6.1 使用请求队列 343
13.6.2 不使用请求队列 347
13.7 实例: vmem_disk驱动 349
13.7.1 vmem_disk的硬件原理 349
13.7.2 vmem_disk驱动模块的加载与卸载 349
13.7.3 vmem_disk设备驱动的block_device_operations 351
13.7.4 vmem_disk的I/O请求处理 352
13.8 Linux MMC子系统 354
13.9 总结 357
第14章 Linux网络设备驱动 358
14.1 Linux网络设备驱动的结构 358
14.1.1 网络协议接口层 359
14.1.2 网络设备接口层 363
14.1.3 设备驱动功能层 367
14.2 网络设备驱动的注册与注销 367
14.3 网络设备的初始化 369
14.4 网络设备的打开与释放 370
14.5 数据发送流程 371
14.6 数据接收流程 372
14.7 网络连接状态 375
14.8 参数设置和统计数据 377
14.9 DM9000网卡设备驱动实例 380
14.9.1 DM9000网卡硬件描述 380
14.9.2 DM9000网卡驱动设计分析 380
14.10 总结 386
第15章 Linux I2C核心、总线与设备驱动 387
15.1 Linux I2C体系结构 387
15.2 Linux I2C核心 394
15.3 Linux I2C适配器驱动 396
15.3.1 I2C适配器驱动的注册与注销 396
15.3.2 I2C总线的通信方法 397
15.4 Linux I2C设备驱动 399
15.4.1 Linux I2C设备驱动的模块加载与卸载 400
15.4.2 Linux I2C设备驱动的数据传输 400
15.4.3 Linux的i2c-dev.c文件分析 400
15.5 Tegra I2C总线驱动实例 405
15.6 AT24xx EEPROM的I2C设备驱动实例 410
15.7 总结 413
第16章 USB主机、设备与Gadget驱动 414
16.1 Linux USB驱动层次 414
16.1.1 主机侧与设备侧USB驱动 414
16.1.2 设备、配置、接口、端点 415
16.2 USB主机控制器驱动 420
16.2.1 USB主机控制器驱动的整体结构 420
16.2.2 实例: Chipidea USB主机驱动 425
16.3 USB设备驱动 425
16.3.1 USB设备驱动的整体结构 425
16.3.2 USB请求块 430
16.3.3 探测和断开函数 435
16.3.4 USB骨架程序 436
16.3.5 实例: USB键盘驱动 443
16.4 USB UDC与Gadget驱动 446
16.4.1 UDC和Gadget驱动的关键数据结构与API 446
16.4.2 实例: Chipidea USB UDC驱动 451
16.4.3 实例: Loopback Function驱动 453
16.5 USB OTG驱动 456
16.6 总结 458
第17章 I2C、SPI、USB驱动架构类比 459
17.1 I2C、SPI、USB驱动架构 459
17.2 I2C主机和外设眼里的Linux世界 460
第18章 ARM Linux设备树 461
18.1 ARM设备树起源 461
18.2 设备树的组成和结构 462
18.2.1 DTS、DTC和DTB等 462
18.2.2 根节点兼容性 468
18.2.3 设备节点兼容性 470
18.2.4 设备节点及label的命名 475
18.2.5 地址编码 477
18.2.6 中断连接 479
18.2.7 GPIO、时钟、pinmux连接 480
18.3 由设备树引发的BSP和驱动变更 484
18.4 常用的OF API 490
18.5 总结 493
第19章 Linux电源管理的系统架构和驱动 494
19.1 Linux电源管理的全局架构 494
19.2 CPUFreq驱动 495
19.2.1 SoC的CPUFreq驱动实现 495
19.2.2 CPUFreq的策略 501
19.2.3 CPUFreq的性能测试和调优 501
19.2.4 CPUFreq通知 502
19.3 CPUIdle驱动 504
19.4 PowerTop 508
19.5 Regulator驱动 508
19.6 OPP 511
19.7 PM QoS 515
19.8 CPU热插拔 518
19.9 挂起到RAM 522
19.10 运行时的PM 528
19.11 总结 534
第20章 Linux芯片级移植及底层驱动 535
20.1 ARM Linux底层驱动的组成和现状 535
20.2 内核节拍驱动 536
20.3 中断控制器驱动 541
20.4 SMP多核启动以及CPU热插拔驱动 549
20.5 DEBUG_LL和EARLY_PRINTK的设置 556
20.6 GPIO驱动 557
20.7 pinctrl驱动 560
20.8 时钟驱动 572
20.9 dmaengine驱动 578
20.10 总结 580
第21章 Linux设备驱动的调试 581
21.1 GDB调试器的用法 581
21.1.1 GDB的基本用法 581
21.1.2 DDD图形界面调试工具 591
21.2 Linux内核调试 594
21.3 内核打印信息——printk() 596
21.4 DEBUG_LL和EARLY_PRINTK 599
21.5 使用“/proc” 600
21.6 Oops 606
21.7 BUG_ON()和WARN_ON() 608
21.8 strace 609
21.9 KGDB 610
21.10 使用仿真器调试内核 612
21.11 应用程序调试 613
21.12 Linux性能监控与调优工具 616
21.13 总结 618
第 1章 计算机工作原理 1
1.1 存储程序计算机工作模型 1
1.2 x86-32汇编基础 3
1.2.1 x86-32 CPU的寄存器 4
1.2.2 数据格式 6
1.2.3 寻址方式和常用汇编指令 7
1.2.4 汇编代码范例解析 11
1.3 汇编一个简单的C语言程序并分析其汇编指令执行过程 13
1.4 单元测试题 26
1.5 实验 27
第 2章 操作系统是如何工作的 29
2.1 函数调用堆栈 29
2.2 借助Linux内核部分源代码模拟存储程序计算机工作模型及时钟中断 32
2.2.1 内嵌汇编 32
2.2.2 虚拟一个x86的CPU硬件平台 34
2.3 在mykernel基础上构造一个简单的操作系统内核 36
2.3.1 代码范例 36
2.3.2 代码分析 42
2.4 单元测试题 48
2.5 实验 48
第3章 MenuOS的构造 50
3.1 Linux内核源代码简介 50
3.2 构造一个简单的Linux内核 56
3.3 跟踪调试Linux内核的启动过程 60
3.4 单元测试题 65
3.5 实验 66
第4章 系统调用的三层机制(上) 67
4.1 用户态、内核态和中断 67
4.2 系统调用概述 70
4.2.1 操作系统提供的API和系统调用的关系 70
4.2.2 触发系统调用及参数传递方式 71
4.3 使用库函数API和C代码中嵌入汇编代码触发同一个系统调用 72
4.3.1 使用库函数API触发一个系统调用 72
4.3.2 内嵌汇编语法简介 73
4.3.3 C代码中嵌入汇编代码触发一个系统调用 75
4.3.4 含两个参数的系统调用范例 76
4.3.5 通用的触发系统调用的库函数syscall 78
4.4 单元测试题 79
4.5 实验 80
第5章 系统调用的三层机制(下) 81
5.1 给MenuOS增加命令 81
5.2 使用gdb跟踪系统调用内核函数sys_time 83
5.3 系统调用在内核代码中的处理过程 85
5.3.1 中断向量0x80和system_call中断服务程序入口的关系 86
5.3.2 在system_call汇编代码中的系统调用内核处理函数 87
5.3.3 整体上理解系统调用的内核处理过程 88
5.4 单元测试题 91
5.5 实验 92
第6章 进程的描述和进程的创建 93
6.1 进程的描述 93
6.2 进程的创建 97
6.2.1 0号进程的初始化 98
6.2.2 内存管理相关代码 99
6.2.3 进程之间的父子、兄弟关系 100
6.2.4 保存进程上下文中CPU相关的一些状态信息的数据结构 101
6.2.5 进程的创建过程分析 103
6.3 单元测试题 120
第7章 可执行程序工作原理 122
7.1 ELF目标文件格式 122
7.1.1 ELF概述 122
7.1.2 ELF格式简介 123
7.1.3 相关操作指令 128
7.2 程序编译 129
7.2.1 预处理 129
7.2.2 编译 130
7.2.3 汇编 131
7.2.4 链接 133
7.3 链接与库 134
7.3.1 符号与符号解析 134
7.3.2 重定位 137
7.3.3 静态链接与动态链接 139
7.4 程序装载 143
7.4.1 程序装载概要 143
7.4.2 fork与execve内核处理过程 148
7.4.3 庄周梦蝶 153
7.4.4 小结 154
7.5 单元测试题 155
7.6 实验 156
第8章 进程的切换和系统的一般执行过程 158
8.1 进程调度的时机 158
8.1.1 硬中断与软中断 158
8.1.2 进程调度时机 159
8.2 调度策略与算法 161
8.2.1 进程的分类 161
8.2.2 调度策略 162
8.2.3 CFS调度算法 164
8.3 进程上下文切换 165
8.3.1 进程执行环境的切换 165
8.3.2 核心代码分析 167
8.4 Linux系统的运行过程 172
8.5 Linux系统构架与执行过程概览 174
8.5.1 Linux操作系统的构架 174
8.5.2 ls命令执行过程即涉及操作系统相关概念 175
8.6 进程调度相关源代码跟踪和分析 176
8.6.1 配置运行MenuOS系统 176
8.6.2 配置gdb远程调试和设置断点 177
8.6.3 使用gdb跟踪分析schedule()函数 177
8.7 单元测试题 179
第一部分 存储技术
第1章 存储技术概论 2
1.1 存储系统元素 2
1.1.1 磁盘驱动器 2
1.1.2 存储设备 4
1.1.3 服务器部件 7
1.1.4 存储软件 9
1.2 存储相关技术 10
1.2.1 备份技术 10
1.2.2 快照技术 13
1.2.3 连续数据保护技术 21
1.2.4 RAID技术 22
1.2.5 “多路径”技术 36
1.2.6 虚拟化技术 39
1.3 网络存储结构 40
1.3.1 直接连接存储 40
1.3.2 网络连接存储 40
1.3.3 存储区域网络 41
1.4 存储I/O通道 41
1.4.1 存储I/O物理通道 42
1.4.2 存储I/O逻辑通道 43
1.4.3 虚拟机I/O逻辑通道 44
1.5 存储应用举例 45
1.5.1 同时提供文件服务和块服务 45
1.5.2 按需扩容、随需取用延缓企业投资 45
1.5.3 计算与存储分离便于故障恢复和系统升级 45
1.5.4 为高可用性集群提供共享存储 46
1.5.5 利用快照技术恢复被病毒破坏的数据 47
1.5.6 基于文件的数据备份和远程镜像方案 47
1.5.7 利用PXE和iSCSI实现远程引导和映像恢复 48
1.5.8 虚拟机故障的检测及迁移 49
第二部分 设备
第2章 Linux驱动模型 52
2.1 概述 52
2.2 引用计数 53
2.3 内核对象及集合 55
2.3.1 创建或初始化内核对象 58
2.3.2 将内核对象添加到sysfs文件系统 59
2.3.3 创建、初始化、添加内核对象集 63
2.3.4 发送内核对象变化事件到用户空间 63
2.4 sysfs文件系统 69
2.4.1 构建内核对象、对象属性和对象关系的内部树 70
2.4.2 对sysfs文件的读/写转换为对属性的show和store操作 73
2.4.3 为具体内核对象定义属性的规范流程 77
2.5 kobject编程模式 80
2.6 驱动模型对象 81
2.6.1 总线类型 82
2.6.2 设备 86
2.6.3 驱动 100
2.6.4 类 105
2.6.5 接口 107
2.7 驱动模型编程模式 108
第3章 PCI子系统 110
3.1 概述 110
3.2 PCI子系统对象 115
3.2.1 pci_bus: PCI总线 116
3.2.2 pci_dev: PCI设备 117
3.3 PCI核心初始化 121
3.4 配置访问方法 124
3.4.1 机制#1方式 126
3.4.2 PCIBIOS方式 128
3.4.3 配置访问接口 133
3.5 PCI总线扫描 133
3.5.1 PCI总线编号范例 133
3.5.2 PCI总线扫描流程 137
3.6 PCI中断路由 160
3.6.1 中断路由初始化 165
3.6.2 查找中断路由表 166
3.6.3 查找中断路由驱动 167
3.6.4 分配ISA IRQ号 171
3.7 PCI资源分配 177
3.7.1 PCI资源分配范例 178
3.7.2 PCI资源分配流程 181
3.8 PCI设备驱动编程模式 193
3.8.1 定义PCI驱动结构 194
3.8.2 定义支持设备ID列表 194
3.8.3 实现probe回调方法 196
3.8.4 实现remove回调方法 198
3.8.5 实现其他回调方法 199
3.8.6 注册与注销PCI驱动 199
第4章 SCSI子系统 201
4.1 概述 201
4.2 SCSI子系统对象 202
4.2.1 scsi_host_template: SCSI主机适配器模板 203
4.2.2 Scsi_Host: SCSI主机适配器 207
4.2.3 scsi_target: SCSI目标节点 210
4.2.4 scsi_device: SCSI逻辑设备 211
4.2.5 scsi_cmnd: SCSI命令 215
4.3 SCSI子系统初始化 216
4.4 添加适配器到系统 216
4.5 SCSI设备探测 222
4.5.1 探测流程入口 224
4.5.2 探测逻辑单元 232
4.5.3 添加SCSI设备 237
4.6 SCSI磁盘驱动 241
4.6.1 同步执行部分 244
4.6.2 异步执行部分 247
4.6.3 重新校验磁盘 249
4.6.4 让磁盘转起来 251
4.7 SCSI命令执行 254
4.8 SCSI错误恢复 259
4.8.1 命令进入错误恢复 261
4.8.2 错误恢复线程执行 262
4.8.3 发送错误恢复命令 275
4.9 SCSI低层驱动编程模式 279
4.9.1 定义主机适配器模板 279
4.9.2 完善探测回调处理逻辑 279
4.9.3 实现queuecommand回调函数 279
4.9.4 实现中断处理函数 283
4.9.5 实现其他回调函数 283
4.9.6 模块加载和卸载 283
第三部分 存储I/O
第5章 块I/O子系统 286
5.1 概述 286
5.2 块I/O子系统对象 287
5.2.1 gendisk: 通用磁盘 289
5.2.2 hd_struct: 分区 291
5.2.3 block_device: 块设备 292
5.2.4 request_queue: 请求队列 293
5.2.5 request: 块设备驱动层请求 296
5.2.6 bio: 通用块层请求 298
5.3 添加磁盘到系统 300
5.3.1 分配通用磁盘描述符 300
5.3.2 添加到sysfs文件系统 302
5.3.3 获取磁盘块设备描述符 305
5.3.4 打开磁盘块设备描述符 306
5.3.5 重新扫描磁盘分区 310
5.3.6 设备号映射机制 314
5.4 请求处理过程 315
5.4.1 上层向块I/O子系统提交请求 315
5.4.2 构造、排序或合并请求 320
5.4.3 SCSI策略例程逐个处理请求 327
5.4.4 为请求构造SCSI命令 334
5.4.5 为SCSI命令准备聚散列表 343
5.4.6 派发SCSI命令到低层驱动 349
5.5 I/O调度算法 352
5.5.1 为请求队列建立关联的I/O调度队列 356
5.5.2 判断bio是否可以被合并到request 356
5.5.3 将请求添加到I/O调度队列或请求队列 359
5.5.4 从I/O调度队列派发请求到请求队列 362
5.6 请求处理完成 366
5.6.1 低层驱动调用完成回调函数 366
5.6.2 引发块I/O子系统的软中断 368
5.6.3 调用请求队列的软中断回调 369
5.6.4 调用上层的完成回调函数 383
5.7 屏障I/O处理 386
5.7.1 屏障I/O接口 386
5.7.2 添加屏障请求 388
5.7.3 处理屏障请求 389
5.7.4 完成屏障请求 393
5.8 完整性保护 396
5.8.1 数据完整性对象 397
5.8.2 为块设备注册完整性能力 400
5.8.3 为bio准备完整性元数据 402
5.8.4 校验完整性元数据 406
5.8.5 修正bio基准标签 408
5.9 磁盘类设备驱动编程模式 411
5.9.1 定义磁盘类设备私有数据结构 411
5.9.2 定义和实现块设备操作表 411
5.9.3 分配和初始化磁盘类设备相关结构 411
5.9.4 为磁盘类设备准备请求队列并添加通用磁盘到系统 412
第6章 Multi-Disk(MD)模块 413
6.1 概述 413
6.2 RAID模块对象 414
6.2.1 mddev_t: RAID设备 414
6.2.2 mdk_rdev_t: 成员磁盘 418
6.2.3 mdk_personality: MD个性 419
6.3 MD模块初始化 420
6.4 MD设备创建 423
6.4.1 从用户空间打开MD设备 424
6.4.2 用户空间发送ioctl创建MD 428
6.4.3 自动检测和运行RAID 439
6.5 MD设备请求执行 439
6.6 MD个性化编程模式 440
6.6.1 定义私有数据结构 441
6.6.2 声明个性化结构 442
6.6.3 实现个性化方法 442
6.6.4 实现模块加载和卸载方法 445
6.7 RAID0模块 445
6.7.1 为RAID0设备构造条带区域 446
6.7.2 查找包含给定偏移的条带区域 451
6.7.3 映射到成员设备及其扇区偏移 451
6.8 RAID5模块 452
6.8.1 RAID5模块对象 452
6.8.2 请求执行过程 459
6.8.3 同步和恢复过程 507
第7章 Device Mapper模块 509
7.1 概述 509
7.2 Device Mapper对象 510
7.2.1 dm_table: 映射表结构 512
7.2.2 dm_target: 映射目标结构 513
7.2.3 mapped_device: 映射设备结构 514
7.2.4 dm_dev: 低层设备结构 515
7.2.5 target_type: 映射目标类型 516
7.3 Device Mapper模块初始化 518
7.4 映射设备的创建 519
7.4.1 分配映射设备描述符 521
7.4.2 加载映射表 526
7.4.3 恢复映射设备 532
7.5 映射设备的请求执行 536
7.5.1 添加到延迟链表 537
7.5.2 分割与处理bio 539
7.6 内核复制线程 549
7.6.1 准备复制任务 551
7.6.2 任务处理流程 553
7.7 Device Mapper目标类型编程模式 556
7.7.1 定义私有数据结构 557
7.7.2 声明目标类型结构 557
7.7.3 实现目标类型方法 557
7.7.4 实现模块加载和卸载方法 558
7.8 条带映射模块 558
7.8.1 构造函数 559
7.8.2 析构函数 562
7.8.3 映射函数 562
7.8.4 end_io函数 563
7.9 快照映射模块 563
7.9.1 快照映射对象 564
7.9.2 快照源构造 569
7.9.3 快照构造 570
7.9.4 快照源读/写 577
7.9.5 快照读/写 585
7.9.6 例外仓库 588
第8章 文件系统 593
8.1 概述 593
8.2 文件系统对象 595
8.2.1 file_system_type: 文件系统类型 596
8.2.2 super_block: VFS超级块 597
8.2.3 inode: VFS索引节点 602
8.2.4 dentry: VFS目录项 610
8.2.5 vfsmount: 文件系统装载 612
8.3 装载文件系统 614
8.3.1 mount系统调用的处理流程 618
8.3.2 构建子文件系统装载实例 621
8.3.3 关联文件系统的超级块实例 623
8.3.4 调用回调函数填充超级块 626
8.3.5 装载到全局文件系统树 630
8.4 路径查找 632
8.4.1 路径查找入口 635
8.4.2 逐个分量解析 637
8.4.3 解析单个分量 642
8.4.4 上溯通过装载点 645
8.4.5 下溯通过装载点 646
8.4.6 处理符号链接 646
8.5 打开文件 651
8.5.1 open系统调用的处理流程 653
8.5.2 解析路径最后一个分量 658
8.5.3 填充文件描述符的内容 662
8.6 读文件 665
8.6.1 read系统调用的处理流程 670
8.6.2 基于缓冲页面构造I/O请求 683
8.6.3 直接针对页面构造I/O请求 690
8.6.4 从文件块编号推导磁盘块编号 696
8.7 写文件 700
8.7.1 write系统调用的处理流程 700
8.7.2 通知为缓冲写请求作准备 707
8.7.3 通知数据已复制到缓冲区 712
8.8 冲刷文件 715
8.8.1 BDI相关对象 715
8.8.2 注册后备设备信息 719
8.8.3 forker线程执行流程 721
8.8.4 flusher线程执行流程 723
8.8.5 同步相关系统调用 749
8.9 块设备文件 761
8.9.1 块设备的主inode和次inode 762
8.9.2 对块设备文件的操作转换为对块设备的操作 764
8.9.3 对块设备文件的读/写作用于块设备之上 767
8.10 文件系统编程模式 767
主要参考文献 769
Chapter 1. UNIX System Overview / UNIX基础知识 1
1.1 Introduction / 引言 1
1.2 UNIX Architecture / UNIX体系结构 1
1.3 Logging In / 登录 2
1.4 Files and Directories / 文件和目录 4
1.5 Input and Output / 输入和输出 8
1.6 Programs and Processes / 程序和进程 10
1.7 Error Handling / 出错处理 14
1.8 User Identification / 用户标识 16
1.9 Signals / 信号 18
1.10 Time Values / 时间值 20
1.11 System Calls and Library Functions / 系统调用和库函数 21
1.12 Summary / 小结 23
Exercises / 习题 24
Chapter 2. UNIX Standardization and Implementations / UNIX标准及实现 25
2.1 Introduction / 引言 25
2.2 UNIX Standardization / UNIX标准化 25
2.2.1 ISO C 25
2.2.2 IEEE POSIX 26
2.2.3 The Single UNIX Specification 30
2.2.4 FIPS 32
2.3 UNIX System Implementations / UNIX系统实现 33
2.3.1 UNIX System V Release 4 / SVR4 33
2.3.2 4.4BSD 34
2.3.3 FreeBSD 34
2.3.4 Linux 35
2.3.5 Mac OS X 35
2.3.6 Solaris 35
2.3.7 Other UNIX Systems / 其他UNIX系统 35
2.4 Relationship of Standards and Implementations / 标准和实现的关系 36
2.5 Limits / 限制 36
2.5.1 ISO C Limits / ISO C限制 37
2.5.2 POSIX Limits / POSIX限制 38
2.5.3 XSI Limits / XSI限制 41
2.5.4 sysconf, pathconf, and fpathconf Functions / 函数sysconf、pathconf和fpathconf 42
2.5.5 Indeterminate Runtime Limits / 不确定的运行时限制 49
2.6 Options / 选项 53
2.7 Feature Test Macros / 功能测试宏 57
2.8 Primitive System Data Types / 基本系统数据类型 58
2.9 Differences Between Standards / 标准之间的冲突 58
2.10 Summary / 小结 60
Exercises / 习题 60
Chapter 3. File I/O / 文件I/O 61
3.1 Introduction / 引言 61
3.2 File Descriptors / 文件描述符 61
3.3 open and openat Functions / 函数open和openat 62
3.4 creat Function / 函数creat 66
3.5 close Function / 函数close 66
3.6 lseek Function / 函数lseek 66
3.7 read Function / 函数read 71
3.8 write Function / 函数write 72
3.9 I/O Efficiency / I/O的效率 72
3.10 File Sharing / 文件共享 74
3.11 Atomic Operations / 原子操作 77
3.12 dup and dup2 Functions / 函数dup和dup2 79
3.13 sync, fsync, and fdatasync Functions / 函数sync、fsync和fdatasync 81
3.14 fcntl Function / 函数fcntl 82
3.15 ioctl Function / 函数ioctl 87
3.16 /dev/fd 88
3.17 Summary / 小结 90
Exercises / 习题 90
Chapter 4. Files and Directories / 文件和目录 93
4.1 Introduction / 引言 93
4.2 stat, fstat, fstatat, and lstat Functions / 函数stat、fstat、fstatat和lstat 93
4.3 File Types / 文件类型 95
4.4 Set-User-ID and Set-Group-ID / 设置用户ID和设置组ID 98
4.5 File Access Permissions / 文件访问权限 99
4.6 Ownership of New Files and Directories / 新文件和目录的所有权 101
4.7 access and faccessat Functions / 函数access和faccessat 102
4.8 umask Function / 函数umask 104
4.9 chmod, fchmod, and fchmodat Functions / 函数chmod、fchmod和fchmodat 106
4.10 Sticky Bit / 粘着位 108
4.11 chown, fchown, fchownat, and lchown Functions / 函数chown、fchown、fchownat和lchown 109
4.12 File Size / 文件长度 111
4.13 File Truncation / 文件截断 112
4.14 File Systems / 文件系统 113
4.15 link, linkat, unlink, unlinkat, and remove Functions / 函数link、linkat、unlink、unlinkat和remove 116
4.16 rename and renameat Functions / 函数rename和renameat 119
4.17 Symbolic Links / 符号链接 120
4.18 Creating and Reading Symbolic Links / 创建和读取符号链接 123
4.19 File Times / 文件的时间 124
4.20 futimens, utimensat, and utimes Functions / 函数futimens、utimensat和utimes 126
4.21 mkdir, mkdirat, and rmdir Functions / 函数mkdir、mkdirat和rmdir 129
4.22 Reading Directories / 读目录 130
4.23 chdir, fchdir, and getcwd Functions / 函数chdir、fchdir和getcwd 135
4.24 Device Special Files / 设备特殊文件 137
4.25 Summary of File Access Permission Bits / 文件访问权限位小结 140
4.26 Summary / 小结 140
Exercises / 习题 141
Chapter 5. Standard I/O Library / 标准I/O库 143
5.1 Introduction / 引言 143
5.2 Streams and FILE Objects / 流和FILE对象 143
5.3 Standard Input, Standard Output, and Standard Error / 标准输入、标准输出和标准错误 145
5.4 Buffering / 缓冲 145
5.5 Opening a Stream / 打开流 148
5.6 Reading and Writing a Stream / 读和写流 150
5.7 Line-at-a-Time I/O / 每次一行I/O 152
5.8 Standard I/O Efficiency / 标准I/O的效率 153
5.9 Binary I/O / 二进制I/O 156
5.10 Positioning a Stream / 定位流 157
5.11 Formatted I/O / 格式化I/O 159
5.12 Implementation Details / 实现细节 164
5.13 Temporary Files / 临时文件 167
5.14 Memory Streams / 内存流 171
5.15 Alternatives to Standard I/O / 标准I/O的替代软件 174
5.16 Summary / 小结 175
Exercises / 习题 175
Chapter 6. System Data Files and Information / 系统数据文件和信息 177
6.1 Introduction / 引言 177
6.2 Password File / 口令文件 177
6.3 Shadow Passwords / 阴影口令 181
6.4 Group File / 组文件 182
6.5 Supplementary Group IDs / 附属组ID 183
6.6 Implementation Differences / 实现区别 184
6.7 Other Data Files / 其他数据文件 185
6.8 Login Accounting / 登录账户记录 186
6.9 System Identification / 系统标识 187
6.10 Time and Date Routines / 时间和日期例程 189
6.11 Summary / 小结 196
Exercises / 习题 196
Chapter 7. Process Environment / 进程环境 197
7.1 Introduction / 引言 197
7.2 main Function / main函数 197
7.3 Process Termination / 进程终止 198
7.4 Command-Line Arguments / 命令行参数 203
7.5 Environment List / 环境表 203
7.6 Memory Layout of a C Program / C程序的存储空间布局 204
7.7 Shared Libraries / 共享库 206
7.8 Memory Allocation / 存储空间分配 207
7.9 Environment Variables / 环境变量 210
7.10 setjmp and longjmp Functions / 函数setjmp和longjmp 213
7.11 getrlimit and setrlimit Functions / 函数getrlimit和setrlimit 220
7.12 Summary / 小结 225
Exercises / 习题 226
Chapter 8. Process Control / 进程控制 227
8.1 Introduction / 引言 227
8.2 Process Identifiers / 进程标识 227
8.3 fork Function / 函数fork 229
8.4 vfork Function / 函数vfork 234
8.5 exit Functions / 函数exit 236
8.6 wait and waitpid Functions / 函数wait和waitpid 238
8.7 waitid Function / 函数waitid 244
8.8 wait3 and wait4 Functions / 函数wait3和wait4 245
8.9 Race Conditions / 竞争条件 245
8.10 exec Functions / 函数exec 249
8.11 Changing User IDs and Group IDs / 更改用户ID和更改组ID 255
8.12 Interpreter Files / 解释器文件 260
8.13 system Function / 函数system 264
8.14 Process Accounting / 进程会计 269
8.15 User Identification / 用户标识 275
8.16 Process Scheduling / 进程调度 276
8.17 Process Times / 进程时间 280
8.18 Summary / 小结 282
Exercises / 习题 283
Chapter 9. Process Relationships / 进程关系 285
9.1 Introduction / 引言 285
9.2 Terminal Logins / 终端登录 285
9.3 Network Logins / 网络登录 290
9.4 Process Groups / 进程组 293
9.5 Sessions / 会话 295
9.6 Controlling Terminal / 控制终端 296
9.7 tcgetpgrp, tcsetpgrp, and tcgetsid Functions / 函数tcgetpgrp、tcsetpgrp和tcgetsid 298
9.8 Job Control / 作业控制 299
9.9 Shell Execution of Programs / Shell执行程序 303
9.10 Orphaned Process Groups / 孤儿进程组 307
9.11 FreeBSD Implementation / FreeBSD实现 310
9.12 Summary / 小结 312
Exercises / 习题 312
Chapter 10. Signals / 信号 313
10.1 Introduction / 引言 313
10.2 Signal Concepts / 信号概念 313
10.3 signal Function / 函数signal 323
10.4 Unreliable Signals / 不可靠的信号 326
10.5 Interrupted System Calls / 中断的系统调用 327
10.6 Reentrant Functions / 可重入函数 330
10.7 SIGCLD Semantics / SIGCLD语义 332
10.8 Reliable-Signal Terminology and Semantics / 可靠信号术语和语义 335
10.9 kill and raise Functions / 函数kill和raise 336
10.10 alarm and pause Functions / 函数alarm和pause 338
10.11 Signal Sets / 信号集 344
10.12 sigprocmask Function / 函数sigprocmask 346
10.13 sigpending Function / 函数sigpending 347
10.14 sigaction Function / 函数sigaction 349
10.15 sigsetjmp and siglongjmp Functions / 函数sigsetjmp和siglongjmp 355
10.16 sigsuspend Function / 函数sigsuspend 359
10.17 abort Function / 函数abort 365
10.18 system Function / 函数system 367
10.19 sleep, nanosleep, and clock_nanosleep Functions / 函数sleep、nanosleep和clock_nanosleep 373
10.20 sigqueue Function / 函数sigqueue 376
10.21 Job-Control Signals / 作业控制信号 377
10.22 Signal Names and Numbers / 信号名和编号 379
10.23 Summary / 小结 381
Exercises / 习题 381
Chapter 11. Threads / 线程 383
11.1 Introduction / 引言 383
11.2 Thread Concepts / 线程概念 383
11.3 Thread Identification / 线程标识 384
11.4 Thread Creation / 线程创建 385
11.5 Thread Termination / 线程终止 388
11.6 Thread Synchronization / 线程同步 397
11.6.1 Mutexes / 互斥量 399
11.6.2 Deadlock Avoidance / 避免死锁 402
11.6.3 pthread_mutex_timedlock Function / 函数pthread_mutex_timedlock 407
11.6.4 Reader-Writer Locks / 读写锁 409
11.6.5 Reader-Writer Locking with Timeouts / 带有超时的读写锁 413
11.6.6 Condition Variables / 条件变量 413
11.6.7 Spin Locks / 自旋锁 417
11.6.8 Barriers / 屏障 418
11.7 Summary / 小结 422
Exercises / 习题 422
Chapter 12. Thread Control / 线程控制 425
12.1 Introduction / 引言 425
12.2 Thread Limits / 线程限制 425
12.3 Thread Attributes / 线程属性 426
12.4 Synchronization Attributes / 同步属性 430
12.4.1 Mutex Attributes / 互斥量属性 430
12.4.2 Reader-Writer Lock Attributes / 读写锁属性 439
12.4.3 Condition Variable Attributes / 条件变量属性 440
12.4.4 Barrier Attributes / 屏障属性 441
12.5 Reentrancy / 重入 442
12.6 Thread-Specific Data / 线程特定数据 446
12.7 Cancel Options / 取消选项 451
12.8 Threads and Signals / 线程和信号 453
12.9 Threads and fork / 线程和fork 457
12.10 Threads and I/O / 线程和I/O 461
12.11 Summary / 小结 462
Exercises / 习题 462
Chapter 13. Daemon Processes / 守护进程 463
13.1 Introduction / 引言 463
13.2 Daemon Characteristics / 守护进程的特征 463
13.3 Coding Rules / 编程规则 466
13.4 Error Logging / 出错记录 469
13.5 Single-Instance Daemons / 单实例守护进程 473
13.6 Daemon Conventions / 守护进程的惯例 474
13.7 Client-Server Model / 客户进程-服务器进程模型 479
13.8 Summary / 小结 480
Exercises / 习题 480
Chapter 14. Advanced I/O / 高级I/O 481
14.1 Introduction / 引言 481
14.2 Nonblocking I/O / 非阻塞I/O 481
14.3 Record Locking / 记录锁 485
14.4 I/O Multiplexing / I/O多路转接 500
14.4.1 select and pselect Functions / 函数select和pselect 502
14.4.2 poll Function / 函数poll 506
14.5 Asynchronous I/O / 异步I/O 509
14.5.1 System V Asynchronous I/O / System V异步I/O 510
14.5.2 BSD Asynchronous I/O / BSD异步I/O 510
14.5.3 POSIX Asynchronous I/O / POSIX异步I/O 511
14.6 readv and writev Functions / 函数readv和writev 521
14.7 readn and writen Functions / 函数readn和writen 523
14.8 Memory-Mapped I/O / 存储映射I/O 525
14.9 Summary / 小结 531
Exercises / 习题 532
Chapter 15. Interprocess Communication / 进程间通信 533
15.1 Introduction / 引言 533
15.2 Pipes / 管道 534
15.3 popen and pclose Functions / 函数popen和pclose 541
15.4 Coprocesses / 协同进程 548
15.5 FIFOs 552
15.6 XSI IPC 556
15.6.1 Identifiers and Keys / 标识符和键 556
15.6.2 Permission Structure / 权限结构 558
15.6.3 Configuration Limits / 结构限制 559
15.6.4 Advantages and Disadvantages / 优点和缺点 559
15.7 Message Queues / 消息队列 561
15.8 Semaphores / 信号量 565
15.9 Shared Memory / 共享存储 571
15.10 POSIX Semaphores / POSIX信号量 579
15.11 Client-Server Properties / 客户进程-服务器进程属性 585
15.12 Summary / 小结 587
Exercises / 习题 587
Chapter 16. Network IPC: Sockets / 网络IPC: 套接字 589
16.1 Introduction / 引言 589
16.2 Socket Descriptors / 套接字描述符 590
16.3 Addressing / 寻址 593
16.3.1 Byte Ordering / 字节序 593
16.3.2 Address Formats / 地址格式 595
16.3.3 Address Lookup / 地址查询 597
16.3.4 Associating Addresses with Sockets / 将套接字与地址关联 604
16.4 Connection Establishment / 建立连接 605
16.5 Data Transfer / 数据传输 610
16.6 Socket Options / 套接字选项 623
16.7 Out-of-Band Data / 带外数据 626
16.8 Nonblocking and Asynchronous I/O / 非阻塞和异步I/O 627
16.9 Summary / 小结 628
Exercises / 习题 628
Chapter 17. Advanced IPC / 高级进程间通信 629
17.1 Introduction / 引言 629
17.2 UNIX Domain Sockets / UNIX域套接字 629
17.3 Unique Connections / 唯一连接 635
17.4 Passing File Descriptors / 传送文件描述符 642
17.5 An Open Server, Version 1 / 打开服务器进程第 1版 653
17.6 An Open Server, Version 2 / 打开服务器进程第 2版 659
17.7 Summary / 小结 669
Exercises / 习题 670
Chapter 18. Terminal I/O / 终端I/O 671
18.1 Introduction / 引言 671
18.2 Overview / 概述 671
18.3 Special Input Characters / 特殊输入字符 678
18.4 Getting and Setting Terminal Attributes / 获得和设置终端属性 683
18.5 Terminal Option Flags / 终端选项标志 683
18.6 stty Command / stty命令 691
18.7 Baud Rate Functions / 波特率函数 692
18.8 Line Control Functions / 行控制函数 693
18.9 Terminal Identification / 终端标识 694
18.10 Canonical Mode / 规范模式 700
18.11 Noncanonical Mode / 非规范模式 703
18.12 Terminal Window Size / 终端窗口大小 710
18.13 termcap, terminfo, and curses / termcap、terminfo和curses 712
18.14 Summary / 小结 713
Exercises / 习题 713
Chapter 19. Pseudo Terminals / 伪终端 715
19.1 Introduction / 引言 715
19.2 Overview / 概述 715
19.3 Opening Pseudo-Terminal Devices / 打开伪终端设备 722
19.4 pty_fork Function / 函数pty_fork 726
19.5 pty Program / pty程序 729
19.6 Using the pty Program / 使用pty程序 733
19.7 Advanced Features / 高级特性 740
19.8 Summary / 小结 741
Exercises / 习题 742
Chapter 20. A Database Library / 数据库函数库 743
20.1 Introduction / 引言 743
20.2 History / 历史 743
20.3 The Library / 函数库 744
20.4 Implementation Overview / 实现概述 746
20.5 Centralized or Decentralized / 集中式还是非集中式 750
20.6 Concurrency / 并发 752
20.7 Building the Library / 构造函数库 753
20.8 Source Code / 源代码 753
20.9 Performance / 性能 781
20.10 Summary / 小结 786
Exercises / 习题 787
Chapter 21. Communicating with a Network Printer / 与网络打印机通信 789
21.1 Introduction / 引言 789
21.2 The Internet Printing Protocol / 网络打印协议 789
21.3 The Hypertext Transfer Protocol / 超文本传输协议HTTP 792
21.4 Printer Spooling / 打印假脱机技术 793
21.5 Source Code / 源代码 795
21.6 Summary / 小结 843
Exercises / 习题 843
Appendix A. Function Prototypes / 函数原型 845
Appendix B. Miscellaneous Source Code / 其他源代码 895
B.1 Our Header File / 本书使用的头文件 895
B.2 Standard Error Routines / 标准出错例程 898
Appendix C. Solutions to Selected Exercises / 部分习题答案 905
Bibliography / 参考书目 947
第1章 入门 1
1.1 unix、linux和gnu简介 1
1.1.1 什么是unix 1
1.1.2 什么是linux 2
1.1.3 gnu项目和自由软件基金会 3
1.1.4 linux发行版 3
1.2 linux程序设计 4
1.2.1 linux程序 4
1.2.2 文本编辑器 5
1.2.3 c语言编译器 5
1.2.4 开发系统导引 7
1.3 获得帮助 12
1.4 小结 14
第2章 shell程序设计 15
2.1 为什么使用shell编程 15
2.2 一点哲学 16
2.3 什么是shell 16
2.4 管道和重定向 18
2.4.1 重定向输出 18
2.4.2 重定向输入 19
.2.4.3 管道 19
2.5 作为程序设计语言的shell 20
2.5.1 交互式程序 20
2.5.2 创建脚本 21
2.5.3 把脚本设置为可执行 22
2.6 shell的语法 23
2.6.1 变量 23
2.6.2 条件 27
2.6.3 控制结构 29
2.6.4 函数 39
2.6.5 命令 42
2.6.6 命令的执行 58
2.6.7 here文档 61
2.6.8 调试脚本程序 63
2.7 迈向图形化: dialog工具 63
2.8 综合应用 68
2.8.1 需求 68
2.8.2 设计 68
2.8.3 应用程序的说明 76
2.9 小结 77
第3章 文件操作 78
3.1 linux文件结构 78
3.1.1 目录 79
3.1.2 文件和设备 79
3.2 系统调用和设备驱动程序 80
3.3 库函数 81
3.4 底层文件访问 82
3.4.1 write系统调用 82
3.4.2 read系统调用 83
3.4.3 open系统调用 84
3.4.4 访问权限的初始值 85
3.4.5 其他与文件管理有关的系统调用 88
3.5 标准i/o库 91
3.5.1 fopen函数 91
3.5.2 fread函数 92
3.5.3 fwrite函数 92
3.5.4 fclose函数 92
3.5.5 fflush函数 93
3.5.6 fseek函数 93
3.5.7 fgetc、getc和getchar函数 93
3.5.8 fputc、putc和putchar函数 94
3.5.9 fgets和gets函数 94
3.6 格式化输入和输出 94
3.6.1 printf、fprintf和sprintf函数 94
3.6.2 scanf、fscanf和sscanf函数 96
3.6.3 其他流函数 98
3.6.4 文件流错误 99
3.6.5 文件流和文件描述符 99
3.7 文件和目录的维护 100
3.7.1 chmod系统调用 100
3.7.2 chown系统调用 100
3.7.3 unlink、link和symlink系统调用 100
3.7.4 mkdir和rmdir系统调用 101
3.7.5 chdir系统调用和getcwd函数 101
3.8 扫描目录 102
3.8.1 opendir函数 102
3.8.2 readdir函数 102
3.8.3 telldir函数 103
3.8.4 seekdir函数 103
3.8.5 closedir函数 103
3.9 错误处理 106
3.9.1 strerror函数 106
3.9.2 perror函数 106
3.10 /proc文件系统 107
3.11 高级主题: fcntl和mmap 110
3.11.1 fcntl系统调用 110
3.11.2 mmap函数 111
3.12 小结 113
第4章 linux环境 114
4.1 程序参数 114
4.1.1 getopt 116
4.1.2 getopt_long 118
4.2 环境变量 120
4.2.1 环境变量的用途 122
4.2.2 environ变量 122
4.3 时间和日期 123
4.4 临时文件 129
4.5 用户信息 131
4.6 主机信息 134
4.7 日志 135
4.8 资源和限制 139
4.9 小结 143
第5章 终端 144
5.1 对终端进行读写 144
5.2 与终端进行对话 149
5.3 终端驱动程序和通用终端接口 151
5.3.1 概述 151
5.3.2 硬件模型 151
5.4 termios结构 152
5.4.1 输入模式 153
5.4.2 输出模式 154
5.4.3 控制模式 155
5.4.4 本地模式 155
5.4.5 特殊控制字符 155
5.4.6 终端速度 158
5.4.7 其他函数 159
5.5 终端的输出 162
5.5.1 终端的类型 163
5.5.2 识别终端类型 163
5.5.3 使用terminfo功能标志 165
5.6 检测击键动作 170
5.7 虚拟控制台 172
5.8 伪终端 173
5.9 小结 174
第6章 使用curses函数库管理基于文本的屏幕 175
6.1 用curses函数库进行编译 175
6.2 curses术语和概念 176
6.3 屏幕 178
6.3.1 输出到屏幕 179
6.3.2 从屏幕读取 180
6.3.3 清除屏幕 180
6.3.4 移动光标 180
6.3.5 字符属性 181
6.4 键盘 183
6.4.1 键盘模式 183
6.4.2 键盘输入 184
6.5 窗口 185
6.5.1 window结构 185
6.5.2 通用函数 186
6.5.3 移动和更新窗口 187
6.5.4 优化屏幕刷新 190
6.6 子窗口 191
6.7 keypad模式 193
6.8 彩色显示 195
6.9 pad 198
6.10 cd唱片应用程序 200
6.10.1 新cd唱片应用程序的开始部分 200
6.10.2 main函数 202
6.10.3 建立菜单 203
6.10.4 操作数据库文件 204
6.10.5 查询cd数据库 209
6.11 小结 213
第7章 数据管理 214
7.1 内存管理 214
7.1.1 简单的内存分配 214
7.1.2 分配大量的内存 215
7.1.3 滥用内存 218
7.1.4 空指针 219
7.1.5 释放内存 220
7.1.6 其他内存分配函数 221
7.2 文件锁定 222
7.2.1 创建锁文件 222
7.2.2 区域锁定 225
7.2.3 锁定状态下的读写操作 227
7.2.4 文件锁的竞争 232
7.2.5 其他锁命令 236
7.2.6 死锁 236
7.3 数据库 237
7.3.1 dbm数据库 237
7.3.2 dbm例程 238
7.3.3 dbm访问函数 239
7.3.4 其他dbm函数 242
7.4 cd唱片应用程序 244
7.4.1 更新设计 244
7.4.2 使用dbm数据库的cd唱片应用程序 245
7.5 小结 262
第8章 mysql 263
8.1 安装 263
8.1.1 mysql软件包 264
8.1.2 安装后的配置 266
8.1.3 安装后的故障修复 270
8.2 mysql管理 270
8.2.1 命令 270
8.2.2 创建用户并赋予权限 274
8.2.3 密码 276
8.2.4 创建数据库 276
8.2.5 数据类型 277
8.2.6 创建表 278
8.2.7 图形化工具 280
8.3 使用c语言访问mysql数据 283
8.3.1 连接例程 283
8.3.2 错误处理 287
8.3.3 执行sql语句 288
8.3.4 更多的函数 301
8.4 cd数据库应用程序 301
8.4.1 创建表 302
8.4.2 添加数据 304
8.4.3 使用c语言访问数据 306
8.5 小结 316
第9章 开发工具 317
9.1 多个源文件带来的问题 317
9.2 make命令和makefile文件 318
9.2.1 makefile的语法 318
9.2.2 make命令的选项和参数 318
9.2.3 makefile文件中的注释 321
9.2.4 makefile文件中的宏 321
9.2.5 多个目标 323
9.2.6 内置规则 325
9.2.7 后缀和模式规则 326
9.2.8 用make管理函数库 327
9.2.9 高级主题: makefile文件和子目录 329
9.2.10 gnu make和gcc 329
9.3 源代码控制 330
9.3.1 rcs 331
9.3.2 sccs 336
9.3.3 rcs和sccs的比较 336
9.3.4 cvs 337
9.3.5 cvs的前端程序 340
9.3.6 subversion 341
9.4 编写手册页 342
9.5 发行软件 345
9.5.1 patch程序 345
9.5.2 其他软件发行工具 347
9.6 rpm软件包 349
9.6.1 使用rpm软件包文件 349
9.6.2 安装rpm软件包 350
9.6.3 创建rpm软件包 350
9.7 其他软件包格式 358
9.8 开发环境 358
9.8.1 kdevelop 358
9.8.2 其他开发环境 360
9.9 小结 360
第10章 调试 361
10.1 错误类型 361
10.2 常用调试技巧 362
10.2.1 有漏洞的程序 362
10.2.2 代码检查 364
10.2.3 取样法 365
10.2.4 程序的受控执行 367
10.3 使用gdb进行调试 368
10.3.1 启动gdb 368
10.3.2 运行一个程序 369
10.3.3 栈跟踪 369
10.3.4 检查变量 370
10.3.5 列出程序源代码 370
10.3.6 设置断点 371
10.3.7 用调试器打补丁 374
10.3.8 深入学习gdb 375
10.4 其他调试工具 375
10.4.1 lint: 清理程序中的“垃圾” 376
10.4.2 函数调用工具 378
10.4.3 用prof/gprof产生执行存档 380
10.5 断言 381
10.6 内存调试 383
10.6.1 electricfence函数库 383
10.6.2 valgrind 384
10.7 小结 387
第11章 进程和信号 388
11.1 什么是进程 388
11.2 进程的结构 388
11.2.1 进程表 390
11.2.2 查看进程 390
11.2.3 系统进程 391
11.2.4 进程调度 393
11.3 启动新进程 394
11.3.1 等待一个进程 399
11.3.2 僵尸进程 401
11.3.3 输入和输出重定向 403
11.3.4 线程 404
11.4 信号 404
11.4.1 发送信号 408
11.4.2 信号集 412
11.5 小结 415
第12章 posix线程 416
12.1 什么是线程 416
12.2 线程的优点和缺点 417
12.3 第一个线程程序 418
12.4 同时执行 421
12.5 同步 423
12.5.1 用信号量进行同步 423
12.5.2 用互斥量进行同步 427
12.6 线程的属性 431
12.7 取消一个线程 435
12.8 多线程 438
12.9 小结 442
第13章 进程间通信: 管道 443
13.1 什么是管道 443
13.2 进程管道 444
13.3 将输出送往popen 445
13.3.1 传递更多的数据 446
13.3.2 如何实现popen 447
13.4 pipe调用 449
13.5 父进程和子进程 451
13.5.1 管道关闭后的读操作 453
13.5.2 把管道用作标准输入和标准输出 454
13.6 命名管道: fifo 456
13.6.1 访问fifo文件 458
13.6.2 高级主题: 使用fifo的客户/服务器应用程序 464
13.7 cd数据库应用程序 468
13.7.1 目标 469
13.7.2 实现 469
13.7.3 客户接口函数 472
13.7.4 服务器接口server.c 478
13.7.5 管道 481
13.7.6 对cd数据库应用程序的总结 487
13.8 小结 487
第14章 信号量、共享内存和消息队列 488
14.1 信号量 488
14.1.1 信号量的定义 489
14.1.2 一个理论性的例子 489
14.1.3 linux的信号量机制 490
14.1.4 使用信号量 492
14.2 共享内存 496
14.2.1 shmget函数 497
14.2.2 shmat函数 497
14.2.3 shmdt 498
14.2.4 shmctl 498
14.3 消息队列 502
14.3.1 msgget函数 502
14.3.2 msgsnd函数 503
14.3.3 msgrcv函数 503
14.3.4 msgctl函数 504
14.4 cd数据库应用程序 507
14.4.1 修改服务器函数 507
14.4.2 修改客户函数 509
14.5 ipc状态命令 511
14.5.1 显示信号量状态 511
14.5.2 显示共享内存状态 511
14.5.3 显示消息队列状态 511
14.6 小结 512
第15章 套接字 513
15.1 什么是套接字 513
15.2 套接字连接 513
15.2.1 套接字属性 517
15.2.2 创建套接字 519
15.2.3 套接字地址 520
15.2.4 命名套接字 520
15.2.5 创建套接字队列 521
15.2.6 接受连接 521
15.2.7 请求连接 522
15.2.8 关闭套接字 523
15.2.9 套接字通信 523
15.2.10 主机字节序和网络字节序 525
15.3 网络信息 527
15.3.1 因特网守护进程(xinetd/inetd) 531
15.3.2 套接字选项 533
15.4 多客户 534
15.4.1 select系统调用 537
15.4.2 多客户 540
15.5 数据报 543
15.6 小结 545
第16章 用gtk+进行gnome编程 546
16.1 x视窗系统简介 546
16.1.1 x服务器 547
16.1.2 x客户端 547
16.1.3 x协议 547
16.1.4 xlib库 547
16.1.5 x工具包 547
16.1.6 窗口管理器 548
16.1.7 创建gui的其他方法——平台无关的窗囗api 548
16.2 gtk+简介 549
16.2.1 glib类型系统 549
16.2.2 gtk+对象系统 550
16.2.3 gnome简介 550
16.2.4 安装gnome/gtk+开发库 551
16.3 事件、信号和回调函数 554
16.4 组装盒构件 556
16.5 gtk+构件 559
16.5.1 gtkwindow 559
16.5.2 gtkentry 560
16.5.3 gtkspinbutton 563
16.5.4 gtkbutton 565
16.5.5 gtktreeview 568
16.6 gnome构件 571
16.7 gnome菜单 572
16.8 对话框 576
16.8.1 gtkdialog 577
16.8.2 模式对话框 578
16.8.3 非模式对话框 579
16.8.4 gtkmessagedialog 580
16.9 cd数据库应用程序 581
16.10 小结 592
第17章 用qt进行kde编程 593
17.1 kde和qt简介 593
17.2 安装qt 594
17.3 信号和槽 596
17.4 qt构件 602
17.4.1 qlineedit 602
17.4.2 qt按钮 605
17.4.3 qcombobox 609
17.4.4 qlistview 613
17.5 对话框 615
17.5.1 qdialog 615
17.5.2 qmessagebox 617
17.5.3 qinputdialog 618
17.5.4 使用qmake简化makefile文件的编写 620
17.6 kde的菜单和工具栏 620
17.7 使用kde/qt编写cd数据库应用程序 624
17.7.1 主窗口 624
17.7.2 addcddialog 627
17.7.3 logondialog 629
17.7.4 main.cpp 630
17.8 小结 632
第18章 linux标准 633
18.1 c编程语言 634
18.1.1 发展历史简介 634
18.1.2 gnu编译器集 634
18.1.3 gcc选项 635
18.2 接口和lsb 636
18.2.1 lsb标准函数库 637
18.2.2 lsb用户和组 638
18.2.3 lsb系统初始化 638
18.3 文件系统层次结构标准 639
18.4 更多标准 642
18.5 小结 642
第1章 引 言1
1.1 BPF和eBPF是什么 1
1.2 跟踪、嗅探、采样、剖析和可观测性分别是什么 2
1.3 BCC、bpftrace和IO Visor 3
1.4 初识BCC: 快速上手 4
1.5 BPF跟踪的能见度 7
1.6 动态插桩: kprobes和uprobes 8
1.7 静态插桩: tracepoint和USDT 9
1.8 初识bpftrace: 跟踪open() 10
1.9 再回到BCC: 跟踪open() 13
1.10 小结 15
第2章 技术背景16
2.1 图释BPF 16
2.2 BPF 17
2.3 扩展版BPF 18
2.4 调用栈回溯 41
2.5 火焰图 44
2.6 事件源 48
2.7 kprobes 49
2.8 uprobes 53
2.9 跟踪点 57
2.10 USDT 62
2.11 动态USDT 66
2.12 性能监控计数器 68
2.13 perf_events 69
2.14 小结 70
第3章 性能分析71
3.1 概览 71
3.2 性能分析方法论 73
3.3 Linux 60秒分析 77
3.4 BCC工具检查清单 84
3.5 小结 90
第4章 BCC91
4.1 BCC的组件 92
4.2 BCC的特性 92
4.3 安装BCC 94
4.4 BCC的工具 96
4.5 funccount 100
4.6 stackcount 105
4.7 trace 110
4.8 argdist 117
4.9 工具文档 121
4.10 开发BCC工具 126
4.11 BCC的内部实现 127
4.12 BCC的调试 128
4.13 小结 136
第5章 bpftrace137
5.1 bpftrace的组件 138
5.2 bpftrace的特性 139
5.3 bpftrace的安装 141
5.4 bpftrace工具 143
5.5 bpftrace单行程序 145
5.6 bpftrace的文档 146
5.7 bpftrace编程 146
5.8 bpftrace的帮助信息 155
5.9 bpftrace的探针类型 157
5.10 bpftrace的控制流 163
5.11 bpftrace的运算符 164
5.12 bpftrace的变量 165
5.13 bpftrace的函数 170
5.14 bpftrace映射表的操作函数 177
5.15 bpftrace的下一步工作 183
5.16 bpftrace的内部运作 185
5.17 bpftrace的调试 186
5.18 小结 190
第6章 CPU.191
6.1 背景知识 192
6.2 传统工具 197
6.3 BPF工具 210
6.4 BPF单行程序 251
6.5 可选练习 253
6.6 小结 254
第7章 内存.255
7.1 背景知识 256
7.2 传统工具 263
7.3 BPF工具 269
7.4 BPF单行程序 288
7.5 可选练习 289
7.6 小结 290
第8章 文件系统291
8.1 背景知识 292
8.2 传统工具 296
8.3 BPF工具 302
8.4 BPF单行程序 353
8.5 可选练习 359
8.6 小结 360
第9章 磁盘I/O361
9.1 背景知识 362
9.2 传统工具 367
9.3 BPF工具 372
9.4 BPF单行程序 406
9.5 可选练习 409
9.6 小结 410
第10章 网络411
10.1 背景知识 412
10.2 传统工具 422
10.3 BPF工具 433
10.4 BPF单行程序 507
10.5 可选练习 513
10.6 小结 515
第11章 安全516
11.1 背景知识 516
11.2 BPF工具 523
11.3 BPF单行程序 542
11.4 小结 544
第12章 编程语言.545
12.1 背景知识 545
12.2 C 551
12.3 Java 560
12.4 bash shell 601
12.5 其他语言 614
12.6 小结 619
第13章 应用程序.620
13.1 背景知识 621
13.2 BPF工具 625
13.3 BPF单行程序 662
13.4 BPF单行程序示范 664
13.5 小结 664
第14章 内核665
14.1 背景知识 666
14.2 分析策略 669
14.3 传统工具 670
14.4 BPF工具 675
14.5 BPF单行程序 697
14.6 BPF单行程序示范 699
14.7 挑战 700
14.8 小结 700
第15章 容器701
15.1 背景知识 701
15.1.1 BPF 的分析能力 703
15.1.2 挑战 703
15.1.3 分析策略 706
15.2 传统工具 706
15.2.1 从主机上分析 706
15.2.2 在容器内分析 707
15.2.3 systemd-cgtop 707
15.2.4 kubectl top 708
15.2.5 docker stats 708
15.2.6 /sys/fs/cgroups 709
15.2.7 perf 709
15.3 BPF工具 710
15.4 BPF单行程序 717
15.5 可选练习 717
15.6 小结 718
第16章 虚拟机管理器719
16.1 背景知识 719
16.2 传统工具 722
16.3 访客系统的BPF工具 723
16.4 宿主机BPF工具 732
16.5 小结 737
第17章 其他BPF性能工具738
17.1 Vector和Performance Co-Pilot(PCP) 738
17.2 Grafana和Performance Co-Pilot 747
17.3 Cloudflare eBPF Prometheus Exporter(配合Grafana) 750
17.4 kubectl-trace 752
17.5 其他工具 755
17.6 小结 755
第18章 建议、技巧和常见问题. 756
18.1 典型事件的频率和额外开销 756
18.2 以49Hz或99Hz为采样频率 760
18.3 黄猪和灰鼠 760
18.4 开发目标软件 762
18.5 学习系统调用 763
18.6 保持简单 764
18.7 事件缺失 764
18.8 调用栈缺失 766
18.9 打印时符号缺失(函数名称) 767
18.10 跟踪时函数缺失 768
18.11 反馈回路 769
18.12 被丢掉的事件 769
附录A bpftrace单行程序770
附录B bpftrace备忘单775
附录C BCC工具的开发778
附录D C.BPF. 793
附录E BPF指令812