目录
1 进程的组织 5
1.1 进程相关数据结构 5
1.1.1 进程的基本信息 6
1.1.2 进程状态 10
1.1.3 TASK_RUNNING状态的进程链表 11
1.1.4 进程间关系 12
1.2 Linux的线程——轻量级进程 15
1.3 进程的创建——do_fork()函数详解 19
1.4 执行进程间切换 33
1.4.1 进程切换之前的工作 33
1.4.2 进程切换实务 —— switch_to宏 37
1.4.3 __switch_to函数 39
1.5 fork与vfock系统调用的区别 42
1.6 内核线程 46
1.7 挂起状态进程的组织 49
1.7.1 等待队列头 49
1.7.2 等待队列的操作 50
1.7.3 进程资源限制 55
1.8 系统调用execve() 56
1.8.1 拷贝用户态参数 57
1.8.2 重要的数据结构 61
1.8.3 search_binary_handler函数 66
1.8.4 目标文件的装载和投入运行 69
1.8.5 库函数 92
2 中断控制 94
2.1 中断的分类 94
2.2 中断的硬件环境 95
2.2.1 外部中断请求IRQ 95
2.2.2 中断描述符表 96
2.2.3 中断和异常的硬件处理 97
2.3 中断描述符表 99
2.3.1 中断门、陷阱门及系统门 99
2.3.2 IDT的初步初始化 100
2.4 异常处理 101
2.5 中断处理 106
2.5.1 中断向量 107
2.5.2 IRQ数据结构 108
2.5.3 do_IRQ()函数 113
2.5.4 中断服务例程 115
2.5.5 IRQ线的动态分配 116
2.6 下半部分 117
2.6.1 软中断 118
2.6.2 tasklet 121
2.6.3 工作队列 122
2.7定时器中断 124
2.7.1 时钟与定时器 124
2.7.2 定时器中断相关的数据结构 127
2.7.3 定时器中断的上半部分 129
3 进程调度 138
3.1 进程调度的概念 138
3.2 进程调度的数据结构和优先级 141
3.2.1 进程的优先级 141
3.2.2 数据结构 145
3.3 调度程序所使用的函数 151
3.3.1 scheduler_tick函数 151
3.3.2 try_to_wake_up函数 156
3.3.3 recalc_task_prio函数 160
3.4 schedule()函数 163
3.4.1 直接调用 163
3.4.2 延迟调用 164
3.4.3 进程切换之前所做的工作 168
3.4.4 完成进程切换时所执行的操作 171
3.4.5 进程切换后所执行的操作 173
3.5 多处理器运行队列的平衡 175
3.5.1 调度域 176
3.5.2 rebalance_tick()函数 178
3.5.3 load_balance()函数 180
3.5.4 move_tasks()函数 183
3.6 进程退出 187
3.6.1 进程终止 187
3.6.2 进程删除 189
4 进程的并发性体现 191
4.1 内核抢占 193
4.1.1 内核抢占概念 193
4.1.2 同步技术总揽 196
4.2 每CPU变量 197
4.3 原子操作 199
4.4 优化屏障和内存壁垒 203
4.4.1 优化屏障 204
4.4.2 内存壁垒 204
4.5 自旋锁 206
4.6 读写自旋锁 211
4.6.1 为读获取和释放一个锁 213
4.6.2 为写获取或释放一个锁 214
4.7 顺序锁 215
4.8 RCU机制 217
4.9 信号量 219
4.9.1 获取和释放信号量 221
4.9.2 读/写信号量 224
4.9.3 补充信号量 225
4.10 禁止本地中断 226
4.10.1 禁止本地中断 227
4.10.2 禁止下半部(可延迟函数) 229
4.11 一些避免竞争条件的实例 231
4.11.1 引用计数器 231
4.11.2 大内核锁 231
4.11.3 内存描述符读/写信号量 232
4.11.4 slab高速缓存链表的信号量 233
4.11.5 索引节点的信号量 233
4.12 内核同步与互斥的总结 233
1