程序员的自我修养 — 读书笔记

[toc]

第一部分 简介

第一章 温故而知新

1.1 从Hello world 说起

1
2
3
4
5
6
#include<stdio.h>

int main(){
printf("hello world");
return 0;
}

hello world 代码引伸的问题:

  • 为什么要编译后再运行
  • C语言在转化为机器码的过程中发生了什么
  • 最后形成的机器码里有什么,是怎么组织、存放的
  • #include<stdio.h> 干了什么?C语言库是什么?怎么存放的?
  • 不同的平台最终编译的结果一样吗?
  • 运行hello world 时,是怎么运行、装载、开始、结束
  • 没有操作系统,能否运行hello world
  • printf 是怎么实现的
  • hello world 运行的时候,在内存中是怎样的。

1.2 万变不离其宗

本书的中所指的计算机:==x86 指令集的 PC==

PC中最重要的3个部件:CPU、内存、IO

image-20210901133852668

3个阶段

  • 早期CPU与内存速率差不多,所以接在系统总线。

  • CPU速率提高,出现北桥【PCI 桥】,协调CPU、内存、显卡的速率

  • 出现南桥,处理相对较慢的设备(键盘、鼠标、usb、硬盘)

1.3 站得高看得远

系统软件

  • 平台性:操作系统、驱动程序
  • 程序开发:编译器、汇编器、链接器

image-20210901135723017

image-20210901141200897

接口

每个层次之间通信的协议,接口的下面是服务的提供者,上面是调用者。(中间层是对下层的包装和扩展)

系统调用

系统调用往往以 软件中断的形式提供。(Linux:0x 80 号中断)

1.4 操作系统做什么

OS的2个主要作用:

  • 提供 抽象接口
  • 管理 硬件资源
1.4.1 不要让CPU打盹
  • 多道程序:监控 CPU,当 CPU 空闲时,执行等待的程序

  • 分时操作系统:程序没运行一段时间,就将 CPU 让给其他程序。

  • 多任务系统:OS 管理硬件资源,OS以高级别运行,进程以低级别运行,进程之间相互隔离。抢占式分配CPU资源,时间到了就暂停进程。

1.4.2 设备驱动

磁盘的组成:

1
2
3
4
5
硬盘(基本存储单位:扇区【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接管内存,并读取所需的数据到内存中。

image-20210901162723883

1.6 众人拾柴火焰高

1.6.1 线程基础

线程的概念

线程,也叫==轻量级进程==,是程序执行的最小单位。线程之间共享进程的资源(如:代码、数据、堆栈)

标准的线程

标准的线程 = 线程 ID + 当前的指令指针PC + 寄存器 + 堆栈

多线程的优势(使用多线程的原因)

  • 多线程可以有效利用等待时间(提高利用率)
  • 多线程可以分工协作,提高效率
  • 程序本身要求并发
  • 多核计算机本身具备多线程的能力,多线程可以充分发挥性能
  • 数据共享效率高

线程的访问权限

image-20210901164201147

线程调度

线程调度:CPU中不断切换不同的线程。

时间片:某个线程执行的时间。

线程调度的 3种状态(至少3种)

  • 就绪
  • 运行
  • 等待

image-20210901164624388

线程调度的 2 种 方式

  • 优先级法 调度
  • 轮转法 调度

线程调度的优先级

线程可以有自己的优先级,优先级可以由用户来设置。

一般来说,频繁等待的线程(IO密集型线程) 比 频繁运行的线程(CPU密集型线程) 更容易获得更高的优先级。(柿子要捡软的捏)

改变线程的优先级(3种方式)

image-20210901165342032

Linux的多线程:

在Linux中,进程和线程实际上都叫 Task任务,只是类似单线程的进程。

不同的任务之间,可以选择共享内存。

linux的多线程操作:

linux的多线程操作

注意:

  • fork:只复制任务,不复制内存(写时复制 COW),需要与 exec 配合使用才能启动==新任务==
  • clone:产生新线程

cow

1.6.2 线程安全
1.6.3 多线程内部情况

第二部分 静态链接

第三部分 装载与动态链接

第四部分 库与运行库