《Linux内核设计与实现 原书第3版》PDF下载

  • 购买积分:12 如何计算积分?
  • 作  者:(美)拉芙著
  • 出 版 社:北京:机械工业出版社
  • 出版年份:2011
  • ISBN:9787111338291
  • 页数:335 页
图书介绍:本书基于Linux 2.6.34内核详细介绍了Linux内核系统,覆盖了从核心内核系统的应用到内核设计与实现等各方面内容。主要内容包括:进程管理、进程调度、时间管理和定时器、系统调用接口、内存寻址、内存管理和页缓存、VFS、内核同步以及调试技术等。同时本书也涵盖了Linux 2.6内核中颇具特色的内容,包括CFS调度程序、抢占式内核、块I/O层以及I/O调度程序等。本书采用理论与实践相结合的路线,能够带领读者快速走进Linux内核世界,真正开发内核代码。本书适合作为高等院校操作系统课程的教材或参考书,也可供相关技术人员参考。

第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使用Git 10

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 GNUC 16

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 forkO 27

3.3.3 vforkO 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 kfifo 79

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初始化一个idr 82

6.3.2分配一个新的UID 82

6.3.3查找UID 83

6.3.4删除UID 84

6.3.5撤销idr 84

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/interrupts 102

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 tasklet 114

8.3.1 tasklet的实现 114

8.3.2使用 tasklet 116

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节拍率:HZ 167

11.2.1理想的HZ值 168

11.2.2高HZ的优势 169

11.2.3高HZ的劣势 169

11.3 jiffies 170

11.3.1 jiffies的内部表示 171

11.3.2 jiffies的回绕 172

11.3.3用户空间和HZ 173

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 timeoutO 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 kmallocO 191

12.4.1 gfp_mask标志 192

12.4.2 kfreeO 195

12.5 vmallocO 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_vmaO 256

15.4.2 find_vma_prevO 257

15.4.3 find_vma_intersectionO 257

15.5 mmapO和do_mmapO:创建地址区间 258

15.6 mummapO和do_mummapO:删除地址区间 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 fiusher线程 268

16.4.1膝上型计算机模式 270

16.4.2历史上的bdflush、kupdated和pdflush 270

16.4.3避免拥塞的方法:使用多线程 271

16.5小结 271

第17章 设备与模块 273

17.1设备类型 273

17.2模块 274

17.2.1 Hello,World 274

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 kobject 283

17.3.2 ktype 284

17.3.3 kset 285

17.3.4 kobject、ktype和kset的相互关系 285

17.3.5管理和操作kobject 286

17.3.6引用计数 287

17.4 sysfs 288

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内核中的bug 296

18.3通过打印来调试 296

18.3.1健壮性 296

18.3.2日志等级 297

18.3.3记录缓冲区 298

18.3.4 syslogd和klogd 298

18.3.5从printfO到printkO的转换 298

18.4 oops 298

18.4.1 ksymoops 300

18.4.2 kallsyms 300

18.5内核调试配置选项 301

18.6引发bug并打印信息 301

18.7神奇的系统请求键 302

18.8内核调试器的传奇 303

18.8.1 gdb 303

18.8.2 kgdb 304

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 typedef 327

20.2.10多用现成的东西 328

20.2.11在源码中减少使用ifdef 328

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