书籍详情
计算机底层的秘密
作者:陆小风(@码农的荒岛求生)
出版社:电子工业出版社
出版时间:2023-04-01
ISBN:9787121452772
定价:¥118.00
购买这本书可以去
内容简介
本书以图解的方式通俗易懂的讲解计算机系统中各项技术的本质,包括编程语言的本质是什么、操作系统、进程线程协程等的本质是什么、到底什么是内存、什么是堆区栈区、内存分配等是怎么一回事、怎样从晶体管构建出CPU、I/O是如何实现的等等,从根源出发,一步步讲解一项技术到底是怎么来的,同时内容可视化——辅助大量精心设计的插图,几乎做到了平均一页有一图,把对技术的理解门槛降到最低。
作者简介
陆小风(@码农的荒岛求生),硕士毕业于北京航空航天大学计算机学院,先后就职于VMware和京东,具有多年软件系统研发经验,擅长用通俗易懂的语言讲解计算机技术。
目录
第 1 章 从编程语言到可执行程序,这是怎么一回事 / 1
1.1 假如你来发明编程语言 / 2
1.1.1 创世纪: CPU 是个聪明的笨蛋 / 3
1.1.2 汇编语言出现了 / 3
1.1.3 底层的细节 vs 高层的抽象 / 4
1.1.4 套路满满:高级编程语言的雏形 / 6
1.1.5 《盗梦空间》与递归:代码的本质 / 7
1.1.6 让计算机理解递归 / 9
1.1.7 优秀的翻译官:编译器 / 9
1.1.8 解释型语言的诞生 / 10
1.2 编译器是如何工作的 / 12
1.2.1 编译器就是一个普通程序,没什么大不了的 / 12
1.2.2 提取出每一个符号 / 13
1.2.3 token 想表达什么含义 / 14
1.2.4 语法树是不是合理的 / 14
1.2.5 根据语法树生成中间代码 / 15
1.2.6 代码生成 / 15
1.3 链接器不能说的秘密 / 16
1.3.1 链接器是如何工作的 / 17
1.3.2 符号决议:供给与需求 / 18
1.3.3 静态库、动态库与可执行文件 / 20
1.3.4 动态库有哪些优势及劣势 / 25
1.3.5 重定位:确定符号运行时地址 / 27
1.3.6 虚拟内存与程序内存布局 / 29
1.4 为什么抽象在计算机科学中如此重要 / 32
1.4.1 编程与抽象 / 32
1.4.2 系统设计与抽象 / 33
1.5 总结 / 34
第 2 章 程序运行起来了,可我对其一无所知 / 35
2.1 从根源上理解操作系统、进程与线程 / 36
2.1.1 一切要从 CPU 说起 / 36
2.1.2 从 CPU 到操作系统 / 37
2.1.3 进程很好,但还不够方便 / 40
2.1.4 从进程演变到线程 / 41
2.1.5 多线程与内存布局 / 44
2.1.6 线程的使用场景 / 44
2.1.7 线程池是如何工作的 / 45
2.1.8 线程池中线程的数量 / 46
2.2 线程间到底共享了哪些进程资源 / 47
2.2.1 线程私有资源 / 47
2.2.2 代码区:任何函数都可放到线程中执行 / 49
2.2.3 数据区:任何线程均可访问数据区变量 / 49
2.2.4 堆区:指针是关键 / 50
2.2.5 栈区:公共的私有数据 / 50
2.2.6 动态链接库与文件 / 52
2.2.7 线程局部存储: TLS / 53
2.3 线程安全代码到底是怎么编写的 / 55
2.3.1 自由与约束 / 55
2.3.2 什么是线程安全 / 56
2.3.3 线程的私有资源与共享资源 / 57
2.3.4 只使用线程私有资源 / 58
2.3.5 线程私有资源 + 函数参数 / 58
2.3.6 使用全局变量 / 60
2.3.7 线程局部存储 / 61
2.3.8 函数返回值 / 62
2.3.9 调用非线程安全代码 / 63
2.3.10 如何实现线程安全代码 / 64
2.4 程序员应如何理解协程 / 65
2.4.1 普通的函数 / 65
2.4.2 从普通函数到协程 / 66
2.4.3 协程的图形化解释 / 68
2.4.4 函数只是协程的一种特例 / 69
2.4.5 协程的历史 / 69
2.4.6 协程是如何实现的 / 70
2.5 彻底理解回调函数 / 71
2.5.1 一切要从这样的需求说起 / 72
2.5.2 为什么需要回调 / 73
2.5.3 异步回调 / 74
2.5.4 异步回调带来新的编程思维 / 75
2.5.5 回调函数的定义 / 77
2.5.6 两种回调类型 / 78
2.5.7 异步回调的问题:回调地狱 / 79
2.6 彻底理解同步与异步 / 80
2.6.1 辛苦的程序员 / 80
2.6.2 打电话与发邮件 / 81
2.6.3 同步调用 / 83
2.6.4 异步调用 / 84
2.6.5 同步、异步在网络服务器中的应用 / 86
2.7 哦!对了,还有阻塞与非阻塞 / 91
2.7.1 阻塞与非阻塞 / 92
2.7.2 阻塞的核心问题: I/O / 92
2.7.3 非阻塞与异步 I/O / 93
2.7.4 一个类比:点比萨 / 94
2.7.5 同步与阻塞 / 95
2.7.6 异步与非阻塞 / 96
2.8 融会贯通:高并发、高性能服务器是如何实现的 / 97
2.8.1 多进程 / 97
2.8.2 多线程 / 98
2.8.3 事件循环与事件驱动 / 99
2.8.4 问题 1 :事件来源与 I/O 多路复用 / 100
2.8.5 问题 2:事件循环与多线程 / 101
2.8.6 咖啡馆是如何运作的: Reactor 模式 / 102
2.8.7 事件循环与 I/O / 103
2.8.8 异步与回调函数 / 103
2.8.9 协程:以同步的方式进行异步编程 / 106
2.8.10 CPU、线程与协程 / 107
2.9 计算机系统漫游:从数据、代码、回调、闭包到容器、虚拟机 / 108
2.9.1 代码、数据、变量与指针 / 108
2.9.2 回调函数与闭包 / 110
2.9.3 容器与虚拟机技术 / 112
2.10 总结 / 114
第 3 章 底层?就从内存这个储物柜开始吧 / 115
3.1 内存的本质、指针及引用 / 116
3.1.1 内存的本质是什么?储物柜、比特、字节与对象 / 116
3.1.2 从内存到变量:变量意味着什么 / 117
3.1.3 从变量到指针:如何理解指针 / 120
3.1.4 指针的威力与破坏性:能力与责任 / 122
3.1.5 从指针到引用:隐藏内存地址 / 123
3.2 进程在内存中是什么样子的 / 124
3.2.1 虚拟内存:眼见未必为实 / 125
3.2.2 页与页表:从虚幻到现实 / 125
3.3 栈区:函数调用是如何实现的 / 127
3.3.1 程序员的好帮手:函数 / 128
3.3.2 函数调用的活动轨迹:栈 / 128
3.3.3 栈帧与栈区:以宏观的角度看 / 130
3.3.4 函数跳转与返回是如何实现的 / 131
3.3.5 参数传递与返回值是如何实现的 / 133
3.3.6 局部变量在哪里 / 134
3.3.7 寄存器的保存与恢复 / 134
3.3.8 Big Picture:我们在哪里 / 134
3.4 堆区:内存动态分配是如何实现的 / 136
3.4.1 为什么需要堆区 / 136
3.4.2 自己动手实现一个 malloc 内存分配器 / 137
3.4.3 从停车场到内存管理 / 138
3.4.4 管理空闲内存块 / 139
3.4.5 跟踪内存分配状态 / 141
3.4.6 怎样选择空闲内存块:分配策略 / 142
3.4.7 分配内存 / 144
3.4.8 释放内存 / 146
3.4.9 高效合并空闲内存块 / 149
3.5 申请内存时底层发生了什么 / 150
3.5.1 三界与 CPU 运行状态 / 150
3.5.2 内核态与用户态 / 151
3.5.3 传送门:系统调用 / 152
3.5.4 标准库:屏蔽系统差异 / 153
3.5.5 堆区内存不够了怎么办 / 154
3.5.6 向操作系统申请内存: brk / 155
3.5.7 冰山之下:虚拟内存才是终极 BOSS / 156
3.5.8 关于分配内存完整的故事 / 156
3.6 高性能服务器内存池是如何实现的 / 157
3.6.1 内存池 vs 通用内存分配器 / 158
3.6.2 内存池技术原理 / 158
3.6.3 实现一个极简内存池 / 159
3.6.4 实现一个稍复杂的内存池 / 160
3.6.5 内存池的线程安全问题 / 161
3.7 与内存相关的经典 bug / 162
3.7.1 返回指向局部变量的指针 / 163
3.7.2 错误地理解指针运算 / 163
3.7.3 解引用有问题的指针 / 164
3.7.4 读取未被初始化的内存 / 165
3.7.5 引用已被释放的内存 / 166
3.7.6 数组下标是从 0 开始的 / 167
3.7.7 栈溢出 / 167
3.7.8 内存泄漏 / 168
3.8 为什么 SSD 不能被当成内存用 / 169
3.8.1 内存读写与硬盘读写的区别 / 169
3.8.2 虚拟内存的限制 / 171
3.8.3 SSD 的使用寿命问题 / 171
3.9 总结 / 171
第 4 章 从晶体管到 CPU,谁能比我更重要 / 173
4.1 你管这破玩意叫 CPU / 174
4.1.1 伟大的发明 / 174
4.1.2 与、或、非: AND 、OR、NOT / 174
4.1.3 道生一、一生二、二生三、三生万物 / 175
4.1.4 计算能力是怎么来的 / 175
4.1.5 神奇的记忆能力 / 176
4.1.6 寄存器与内存的诞生 / 177
4.1.7 硬件还是软件?通用设备 / 178
4.1.8 硬件的基本功:机器指令 / 179
4.1.9 软件与硬件的接口:指令集 / 179
4.1.10 指挥家,让我们演奏一曲
1.1 假如你来发明编程语言 / 2
1.1.1 创世纪: CPU 是个聪明的笨蛋 / 3
1.1.2 汇编语言出现了 / 3
1.1.3 底层的细节 vs 高层的抽象 / 4
1.1.4 套路满满:高级编程语言的雏形 / 6
1.1.5 《盗梦空间》与递归:代码的本质 / 7
1.1.6 让计算机理解递归 / 9
1.1.7 优秀的翻译官:编译器 / 9
1.1.8 解释型语言的诞生 / 10
1.2 编译器是如何工作的 / 12
1.2.1 编译器就是一个普通程序,没什么大不了的 / 12
1.2.2 提取出每一个符号 / 13
1.2.3 token 想表达什么含义 / 14
1.2.4 语法树是不是合理的 / 14
1.2.5 根据语法树生成中间代码 / 15
1.2.6 代码生成 / 15
1.3 链接器不能说的秘密 / 16
1.3.1 链接器是如何工作的 / 17
1.3.2 符号决议:供给与需求 / 18
1.3.3 静态库、动态库与可执行文件 / 20
1.3.4 动态库有哪些优势及劣势 / 25
1.3.5 重定位:确定符号运行时地址 / 27
1.3.6 虚拟内存与程序内存布局 / 29
1.4 为什么抽象在计算机科学中如此重要 / 32
1.4.1 编程与抽象 / 32
1.4.2 系统设计与抽象 / 33
1.5 总结 / 34
第 2 章 程序运行起来了,可我对其一无所知 / 35
2.1 从根源上理解操作系统、进程与线程 / 36
2.1.1 一切要从 CPU 说起 / 36
2.1.2 从 CPU 到操作系统 / 37
2.1.3 进程很好,但还不够方便 / 40
2.1.4 从进程演变到线程 / 41
2.1.5 多线程与内存布局 / 44
2.1.6 线程的使用场景 / 44
2.1.7 线程池是如何工作的 / 45
2.1.8 线程池中线程的数量 / 46
2.2 线程间到底共享了哪些进程资源 / 47
2.2.1 线程私有资源 / 47
2.2.2 代码区:任何函数都可放到线程中执行 / 49
2.2.3 数据区:任何线程均可访问数据区变量 / 49
2.2.4 堆区:指针是关键 / 50
2.2.5 栈区:公共的私有数据 / 50
2.2.6 动态链接库与文件 / 52
2.2.7 线程局部存储: TLS / 53
2.3 线程安全代码到底是怎么编写的 / 55
2.3.1 自由与约束 / 55
2.3.2 什么是线程安全 / 56
2.3.3 线程的私有资源与共享资源 / 57
2.3.4 只使用线程私有资源 / 58
2.3.5 线程私有资源 + 函数参数 / 58
2.3.6 使用全局变量 / 60
2.3.7 线程局部存储 / 61
2.3.8 函数返回值 / 62
2.3.9 调用非线程安全代码 / 63
2.3.10 如何实现线程安全代码 / 64
2.4 程序员应如何理解协程 / 65
2.4.1 普通的函数 / 65
2.4.2 从普通函数到协程 / 66
2.4.3 协程的图形化解释 / 68
2.4.4 函数只是协程的一种特例 / 69
2.4.5 协程的历史 / 69
2.4.6 协程是如何实现的 / 70
2.5 彻底理解回调函数 / 71
2.5.1 一切要从这样的需求说起 / 72
2.5.2 为什么需要回调 / 73
2.5.3 异步回调 / 74
2.5.4 异步回调带来新的编程思维 / 75
2.5.5 回调函数的定义 / 77
2.5.6 两种回调类型 / 78
2.5.7 异步回调的问题:回调地狱 / 79
2.6 彻底理解同步与异步 / 80
2.6.1 辛苦的程序员 / 80
2.6.2 打电话与发邮件 / 81
2.6.3 同步调用 / 83
2.6.4 异步调用 / 84
2.6.5 同步、异步在网络服务器中的应用 / 86
2.7 哦!对了,还有阻塞与非阻塞 / 91
2.7.1 阻塞与非阻塞 / 92
2.7.2 阻塞的核心问题: I/O / 92
2.7.3 非阻塞与异步 I/O / 93
2.7.4 一个类比:点比萨 / 94
2.7.5 同步与阻塞 / 95
2.7.6 异步与非阻塞 / 96
2.8 融会贯通:高并发、高性能服务器是如何实现的 / 97
2.8.1 多进程 / 97
2.8.2 多线程 / 98
2.8.3 事件循环与事件驱动 / 99
2.8.4 问题 1 :事件来源与 I/O 多路复用 / 100
2.8.5 问题 2:事件循环与多线程 / 101
2.8.6 咖啡馆是如何运作的: Reactor 模式 / 102
2.8.7 事件循环与 I/O / 103
2.8.8 异步与回调函数 / 103
2.8.9 协程:以同步的方式进行异步编程 / 106
2.8.10 CPU、线程与协程 / 107
2.9 计算机系统漫游:从数据、代码、回调、闭包到容器、虚拟机 / 108
2.9.1 代码、数据、变量与指针 / 108
2.9.2 回调函数与闭包 / 110
2.9.3 容器与虚拟机技术 / 112
2.10 总结 / 114
第 3 章 底层?就从内存这个储物柜开始吧 / 115
3.1 内存的本质、指针及引用 / 116
3.1.1 内存的本质是什么?储物柜、比特、字节与对象 / 116
3.1.2 从内存到变量:变量意味着什么 / 117
3.1.3 从变量到指针:如何理解指针 / 120
3.1.4 指针的威力与破坏性:能力与责任 / 122
3.1.5 从指针到引用:隐藏内存地址 / 123
3.2 进程在内存中是什么样子的 / 124
3.2.1 虚拟内存:眼见未必为实 / 125
3.2.2 页与页表:从虚幻到现实 / 125
3.3 栈区:函数调用是如何实现的 / 127
3.3.1 程序员的好帮手:函数 / 128
3.3.2 函数调用的活动轨迹:栈 / 128
3.3.3 栈帧与栈区:以宏观的角度看 / 130
3.3.4 函数跳转与返回是如何实现的 / 131
3.3.5 参数传递与返回值是如何实现的 / 133
3.3.6 局部变量在哪里 / 134
3.3.7 寄存器的保存与恢复 / 134
3.3.8 Big Picture:我们在哪里 / 134
3.4 堆区:内存动态分配是如何实现的 / 136
3.4.1 为什么需要堆区 / 136
3.4.2 自己动手实现一个 malloc 内存分配器 / 137
3.4.3 从停车场到内存管理 / 138
3.4.4 管理空闲内存块 / 139
3.4.5 跟踪内存分配状态 / 141
3.4.6 怎样选择空闲内存块:分配策略 / 142
3.4.7 分配内存 / 144
3.4.8 释放内存 / 146
3.4.9 高效合并空闲内存块 / 149
3.5 申请内存时底层发生了什么 / 150
3.5.1 三界与 CPU 运行状态 / 150
3.5.2 内核态与用户态 / 151
3.5.3 传送门:系统调用 / 152
3.5.4 标准库:屏蔽系统差异 / 153
3.5.5 堆区内存不够了怎么办 / 154
3.5.6 向操作系统申请内存: brk / 155
3.5.7 冰山之下:虚拟内存才是终极 BOSS / 156
3.5.8 关于分配内存完整的故事 / 156
3.6 高性能服务器内存池是如何实现的 / 157
3.6.1 内存池 vs 通用内存分配器 / 158
3.6.2 内存池技术原理 / 158
3.6.3 实现一个极简内存池 / 159
3.6.4 实现一个稍复杂的内存池 / 160
3.6.5 内存池的线程安全问题 / 161
3.7 与内存相关的经典 bug / 162
3.7.1 返回指向局部变量的指针 / 163
3.7.2 错误地理解指针运算 / 163
3.7.3 解引用有问题的指针 / 164
3.7.4 读取未被初始化的内存 / 165
3.7.5 引用已被释放的内存 / 166
3.7.6 数组下标是从 0 开始的 / 167
3.7.7 栈溢出 / 167
3.7.8 内存泄漏 / 168
3.8 为什么 SSD 不能被当成内存用 / 169
3.8.1 内存读写与硬盘读写的区别 / 169
3.8.2 虚拟内存的限制 / 171
3.8.3 SSD 的使用寿命问题 / 171
3.9 总结 / 171
第 4 章 从晶体管到 CPU,谁能比我更重要 / 173
4.1 你管这破玩意叫 CPU / 174
4.1.1 伟大的发明 / 174
4.1.2 与、或、非: AND 、OR、NOT / 174
4.1.3 道生一、一生二、二生三、三生万物 / 175
4.1.4 计算能力是怎么来的 / 175
4.1.5 神奇的记忆能力 / 176
4.1.6 寄存器与内存的诞生 / 177
4.1.7 硬件还是软件?通用设备 / 178
4.1.8 硬件的基本功:机器指令 / 179
4.1.9 软件与硬件的接口:指令集 / 179
4.1.10 指挥家,让我们演奏一曲
猜您喜欢