程序员的自我修养 — 读书笔记
[toc]
第一部分 简介
第一章 温故而知新
1.1 从Hello world 说起
1 |
|
hello world 代码引伸的问题:
- 为什么要编译后再运行
- C语言在转化为机器码的过程中发生了什么
- 最后形成的机器码里有什么,是怎么组织、存放的
- #include<stdio.h> 干了什么?C语言库是什么?怎么存放的?
- 不同的平台最终编译的结果一样吗?
- 运行hello world 时,是怎么运行、装载、开始、结束
- 没有操作系统,能否运行hello world
- printf 是怎么实现的
- hello world 运行的时候,在内存中是怎样的。
1.2 万变不离其宗
本书的中所指的计算机:==x86 指令集的 PC==
PC中最重要的3个部件:CPU、内存、IO
3个阶段
早期CPU与内存速率差不多,所以接在系统总线。
CPU速率提高,出现北桥【PCI 桥】,协调CPU、内存、显卡的速率
出现南桥,处理相对较慢的设备(键盘、鼠标、usb、硬盘)
1.3 站得高看得远
系统软件
- 平台性:操作系统、驱动程序
- 程序开发:编译器、汇编器、链接器
接口
每个层次之间通信的协议,接口的下面是服务的提供者,上面是调用者。(中间层是对下层的包装和扩展)
系统调用
系统调用往往以 软件中断的形式提供。(Linux:0x 80 号中断)
1.4 操作系统做什么
OS的2个主要作用:
- 提供 抽象接口
- 管理 硬件资源
1.4.1 不要让CPU打盹
多道程序:监控 CPU,当 CPU 空闲时,执行等待的程序
分时操作系统:程序没运行一段时间,就将 CPU 让给其他程序。
多任务系统:OS 管理硬件资源,OS以高级别运行,进程以低级别运行,进程之间相互隔离。抢占式分配CPU资源,时间到了就暂停进程。
1.4.2 设备驱动
磁盘的组成:
1 | 硬盘(基本存储单位:扇区【sector,512 B】) |
磁盘中,扇区的划分:LBA(将所有扇区从0开始编号,形成逻辑扇区,再由磁盘自己来将逻辑扇区转化为真实的盘面、磁道)
1.5 内存不够怎么办
问题:不隔离、效率低、地址不确定
解决:加一个中间层 =》 虚拟地址
1.5.1 隔离
进程只关注自己,在进程看来自己独享内存和cpu,进程只能访问自己的空间
地址空间
- 虚拟地址
- 物理地址
1.5.2 分段
分段:将虚拟地址分割为【 段选择子(段号+标志)+ 段内偏移】。其中,段号可以找到段表,段表由CPU中的MMU来管理,MMU 负责虚拟地址与物理地址的映射。
分段的方式解决了1.5小节一开始提到的==【地址不隔离、地址不确定】==的 2个 问题,还存在着==【内存使用效率低】==的问题,该问题可以通过==内存分页==来解决。
1.5.3 分页
分页:将内存分为若干个==固定大小的页==,页的大小由==硬件来决定==。(Linux:4 KB/页)
页的分类
- 虚拟页:虚拟地址
- 物理页:物理地址的页(内存:存放经常使用的页)
- 磁盘页:磁盘中的页(存放不常使用的页)
多个==虚拟页==映射到==同一个物理页== =》 内存共享
进程需要用到虚拟页的内容,但内存中不存在虚拟页的内容时,产生==页错误==,由OS接管内存,并读取所需的数据到内存中。
1.6 众人拾柴火焰高
1.6.1 线程基础
线程的概念
线程,也叫==轻量级进程==,是程序执行的最小单位。线程之间共享进程的资源(如:代码、数据、堆栈)
标准的线程
标准的线程 = 线程 ID + 当前的指令指针PC + 寄存器 + 堆栈
多线程的优势(使用多线程的原因)
- 多线程可以有效利用等待时间(提高利用率)
- 多线程可以分工协作,提高效率
- 程序本身要求并发
- 多核计算机本身具备多线程的能力,多线程可以充分发挥性能
- 数据共享效率高
线程的访问权限
线程调度
线程调度:CPU中不断切换不同的线程。
时间片:某个线程执行的时间。
线程调度的 3种状态(至少3种)
- 就绪
- 运行
- 等待
线程调度的 2 种 方式
- 优先级法 调度
- 轮转法 调度
线程调度的优先级
线程可以有自己的优先级,优先级可以由用户来设置。
一般来说,频繁等待的线程(IO密集型线程
) 比 频繁运行的线程(CPU密集型线程
) 更容易获得更高的优先级
。(柿子要捡软的捏)
改变线程的优先级(3种方式)
Linux的多线程:
在Linux中,进程和线程实际上都叫 Task任务,只是类似单线程的进程。
不同的任务之间,可以选择共享内存。
linux的多线程操作:
注意:
- fork:只复制任务,不复制内存(写时复制 COW),需要与 exec 配合使用才能启动==新任务==
- clone:产生新线程