描述
开 本: 16开纸 张: 胶版纸包 装: 平装-胶订是否套装: 否国际标准书号ISBN: 9787111604082
本书分模块介绍了Linux操作系统的内核设计和实现,针对关键概念、算法和数据结构做了重点的讲解。同时,对诸多经典应用程序进行了剖析,如Nginx、Memcached、Redis、LVS等,讲解如何利用操作系统提供的底层支持进行合理的应用设计和实现。
本书由架构师亲力打造,分享了他十多年后端开发经验,特别是围绕Linux系统进行的服务开发经验。本书共8章,主要内容包括:第1章介绍Linux对进程和线程的实现原理,并分析了Memcached和Nginx工作进程池模型的实现;第2章介绍并发的概念以及Linux中的并发相关工具,然后分析常见开源软件的并发问题;第3章介绍Linux是如何进行内存管理的,分析了Memcached和Redis的内存管理机制。第4章介绍Linux系统对中断进行的封装和实现;第5章介绍I/O的全过程,以及某些开源系统中I/O相关调用的实现等;第6章介绍Linux文件系统的整体架构及核心概念,然后介绍ext4文件系统的特点,以及TFS小文件系统的设计思路;第7章介绍Linux进程隔离技术,以及Docker容器的部分实现;第8章介绍Linux网络层数据的流转过程,以及lvs如何在netfilter上定制,后分析了Nginx服务器socket监听初始化的过程。
Contents 目 录
前言
第1章 进程与线程 1
1.1 进程和线程的概念 1
1.1.1 进程的历史 1
1.1.2 线程的不同玩法 3
1.2 Linux对进程和线程的实现 5
1.2.1 Linux中的进程实现 6
1.2.2 进程创建之后 12
1.2.3 内核线程和进程的区别 13
1.2.4 用户线程库pthread 15
1.3 进程的调度 16
1.3.1 进程调度机制的架构 16
1.3.2 进程切换的原理 19
1.3.3 调度中的CPU亲和度 21
1.4 在应用程序中管理进程和线程 22
1.4.1 Memcached线程池模型分析 22
1.4.2 Nginx进程模型分析 24
1.5 处理进程和线程的相关工具 25
1.5.1 开发环境调试线程 25
1.5.2 进程崩溃调试方法 26
1.5.3 strace工具 28
1.5.4 SystemTap工具 29
1.5.5 DTrace工具 30
1.6 本章小结 32
第2章 并发 33
2.1 什么是并发 34
2.1.1 并发是如何产生的 34
2.1.2 并发会带来什么问题 34
2.1.3 如何解决并发带来的问题 35
2.2 操作系统会在哪些场景遇到并发 35
2.3 Linux中并发工具的实现 37
2.3.1 原子变量 37
2.3.2 自旋锁 38
2.3.3 信号量 42
2.3.4 互斥锁 43
2.3.5 读写锁 43
2.3.6 抢占 44
2.3.7 per-cpu变量 45
2.3.8 RCU机制 48
2.3.9 内存屏障 51
2.4 常见开源软件中的并发问题分析 54
2.4.1 Nginx原子性 54
2.4.2 Memcached中的互斥锁 55
2.4.3 Redis无锁解决方案 56
2.4.4 Linux中惊群问题分析 57
2.4.5 解决MyCat同步问题 65
2.4.6 false-sharing问题解决方案 67
2.5 本章小结 69
第3章 内存管理 70
3.1 为什么需要内存管理 71
3.2 MMU和地址空间 73
3.2.1 虚拟地址、线性地址、物理地址 73
3.2.2 MMU的内存管理机制 74
3.3 Linux中的分段和分页机制 79
3.3.1 分段机制 79
3.3.2 分页机制 80
3.4 Linux的内存管理 82
3.4.1 物理内存管理 83
3.4.2 进程地址空间管理 86
3.5 Linux的内存分配和管理 89
3.5.1 物理内存分配算法 89
3.5.2 slab分配器 95
3.5.3 内核态内存管理 105
3.5.4 用户态内存申请 109
3.6 栈内存分配和管理 109
3.7 内存管理案例分析 110
3.7.1 Memcached内存管理机制分析 110
3.7.2 Redis内存管理机制分析 113
3.8 本章小结 115
第4章 中断机制 116
4.1 x86系统的中断机制 116
4.1.1 x86中断架构 117
4.1.2 x86在保护模式下的中断 117
4.2 Linux对中断的支持和实现 119
4.2.1 初始化IRQ中断门 120
4.2.2 中断响应流程 120
4.2.3 中断回调handler注册过程 122
4.3 Linux加速中断处理的机制 122
4.3.1 软中断 122
4.3.2 tasklet 126
4.3.3 工作队列 128
4.4 系统调用 132
4.5 时钟中断 134
4.6 信号处理机制 135
4.7 Nginx信号处理机制 139
4.8 本章小结 141
第5章 输入输出 142
5.1 I/O在Linux中的生命周期 143
5.1.1 vfs层 143
5.1.2 文件系统层 144
5.1.3 Block层 152
5.1.4 scsi层 156
5.1.5 I/O流程总结 157
5.2 I/O调度器 159
5.3 多队列机制 161
5.4 I/O多路复用实现 163
5.5 Redis对epoll的封装 170
5.6 Nginx文件异步I/O 175
5.7 tail指令为何牛 177
5.8 零拷贝技术应用分析 179
5.8.1 mmap 180
5.8.2 sendf?ile 181
5.8.3 mmap和sendf?ile在开源软件中的使用 183
5.9 本章小结 186
第6章 文件系统 187
6.1 Linux文件系统架构 187
6.2 文件系统的主要功能 189
6.2.1 文件系统的安装 190
6.2.2 文件路径查找 191
6.3 ext4文件系统 201
6.3.1 磁盘布局 201
6.3.2 inode定位 203
6.3.3 碎片问题解决方案 204
6.3.4 extent tree结构 204
6.4 淘宝TFS小文件系统分析 206
6.5 本章小结 207
第7章 Linux的进程隔离技术与Docker容器 208
7.1 虚拟化相关技术 208
7.2 Linux进程隔离技术 209
7.2.1 chroot 209
7.2.2 namespace 210
7.2.3 cgroup 212
7.3 Docker容器的部分实现 219
7.3.1 新版Docker架构 220
7.3.2 containerd的实现 221
7.4 本章小结 241
第8章 Linux网络层数据流分析 242
8.1 数据在网络层的流转 242
8.1.1 sk_buff结构 243
8.1.2 数据流转过程 244
8.2 socket接口层的实现 248
8.2.1 socket系统初始化 248
8.2.2 socket创建 250
8.2.3 socket绑定 251
8.2.4 socket监听 253
8.2.5 socket接受连接 254
8.2.6 新连接的到来 257
8.2.7 socket整体流程 259
8.3 netf?ilter和lvs 260
8.3.1 netf?ilter 260
8.3.2 lvs 263
8.4 网络相关的一些参数 265
8.4.1 Java socket相关的参数 265
8.4.2 Linux TCP相关队列 267
8.5 Nginx服务器监听socket初始化过程 268
8.6 本章小结 274
Preface?前 言
随着计算机技术的发展,开发人员想要根据业务需求写出相关实现代码还是比较容易的,因为已经有了很多工具、组件、库等可帮助我们实现功能。开发人员很少会自己裸写代码,不会从底层到上层全部由自己来实现。于是,很多开发人员一旦遇到程序出现问题就会茫然失措,不知道该如何处理,甚至故障诊断和分析都成了一门高深的技术难题。
我们做任何一件事情都应该知其然,并知其所以然。操作系统是计算机的基础,所有的应用程序都是运行在操作系统之上的,所以,不管开发人员使用什么语言,开发什么行业的应用,都应该了解操作系统的原理与实现细节。
本人因为长期从事系统架构相关的工作,在涉及一些中间件或者基础组件的研发工作过程中,经常会与操作系统打交道,特别是Linux内核。我个人认为,所有应用开发人员都应该了解操作系统的实现原理和思路。Linux是人类工程史上的一个奇迹(那么大的工程,那么多人在网络上维护,能保持那么高的可用性),Linux内核作为一个开放源码的工程,在很多方面值得我们学习和借鉴。其实在工程领域,很多问题的解题思路是类似的,掌握内核的实现,对于我们更好地编写高性能、高可靠性的程序有很大帮助,也更加利于千里定位故障,秒杀Bug。
Linux体系结构
操作系统是所有应用程序生长的河床,它帮我们屏蔽各种硬件的细节,并且抽象出各种系统调用供应用开发人员来使用。
下面来介绍一下本书将要介绍的Linux内核的体系结构(图1),以便于后续章节展开分析。
图1 Linux内核的体系结构
整个Linux内核可以分为4层:
驱动管理层,驱动并管理外部一些硬件设备,例如磁盘、网卡等。
工具层,内核抽象出一些通用组件便于自己使用,例如并发管理中的一些锁、per-cpu变量等工具,另外还有中断机制,也给进程管理、信号处理等提供了基础功能。
系统能力层,操作系统的功能包括进程管理、内存管理、文件系统、I/O管理、网络等,这些功能都是基于工具层和驱动管理层提供的能力来构建的。
系统调用接口层(syscall),给应用程序开发人员提供相关接口。因为系统调用的使用成本较高,参数也比较多,需要对内核有较多了解,所以,又抽象出一些libc等库函数来封装系统调用,应用开发人员一般都是通过libc等库来与内核打交道的。
推荐预备知识
理论上说,只需具备一门编程语言的开发基础就能阅读本书,不过,为了更好地研究操作系统,我推荐大家先阅读下面的书籍:
《80×86汇编语言程序设计》(沈美明等),与CPU打交道好的方式还是汇编语言,另外,了解汇编语言也方便更好地掌握计算机体系结构,进而深入理解系统的工作原理。
《Intel开发手册卷3》,Intel公司的开发手册,可以让读者了解CPU的工作原理、基本指令集等。CPU相关的功能也是内核为重要的部分之一。
《自己动手编写操作系统》(于渊),该书通过编写一个简易系统,让读者更加了解硬件的工作原理。
《Linux内核完全注释》(v0.11)(赵炯),通过对0.11版本的Linux学习,可以了解早期的内核架构,这对学习新版本内核也有很大的帮助。
《软件调试的艺术》(马特洛夫),作为一名程序员,掌握基本的调试技能是必须的。
《程序员的自我修养:链接、装载与库》(潘爱民等),这本书有助于掌握编译、链接的原理,对了解操作系统编译、运行以及应用程序的装载原理有很大帮助。
当然,掌握C语言也是必须的,毕竟Linux内核是用C语言开发的,如果是C语言新手,可以先阅读Memcached的源码,因为作者的代码写得比较清晰,易于理解,初学者都可以轻松上手。
本书章节概述
由于篇幅有限,本书并没有详细介绍Linux内核的所有知识点,比如系统的启动过程,虽然对于一个内核的实现来讲,系统启动是非常重要的,但本书考虑的场景都是围绕系统启动之后提供的功能来展开的,所以本书没有包括这部分内容。
本书共分为8章,分别介绍Linux操作系统的各个模块。对于Linux内核来讲,各个模块之间虽然都是紧密结合的,但是从系统领域模型的角度,每一章都可以独立展开,读者既可以从头开始阅读,也可以选择自己感兴趣的章节进行学习。
第1章介绍进程和线程的概念、历史、实现原理、应用场景等,然后介绍Linux对进程和线程的实现,以及调度的机制、进程CPU亲和度等,并分析了Memcached线程池模型和Nginx工作进程池模型的实现,后介绍了进程调试分析监控等工具的用法,包括gdb、coredump、strace、SystemTap、DTrace等调试工具。
第2章介绍并发的概念及其引发的相关问题,接着介绍操作系会在哪些场景遇到并发,进而分析Linux中的并发相关工具,如atomicspin_lock、semaphore、mutex、读写锁、per-cpu、抢占、内存屏障、RCU机制,后介绍常见开源软件中的并发问题分析,如Nginx的原子性、Memcached的互斥锁、Linux中惊群问题分析、解决MyCat中的同步问题、伪共享问题解决方案等。
第3章首先介绍内存在体系结构中的作用,以及在使用中会遇到什么问题,接着介绍MMU的内存管理机制、线性地址、物理地址、虚拟地址等。接下来分析Linux是如何进行内存管理的,包括整体架构以及伙伴算法、slab分配器、kmalloc、
评论
还没有评论。