温故而之新
带着问题看本书
#include <stdio.h>
int main() {
printf("Hello World\n"); return 0;
}
- 程序为什么要被编译器编译了之后才可以运行?
- 编译器在把 C 语言程序转换成可以执行的机器码的过程中做了什么,怎么做的?
- 最后编译出来的可执行文件里面是什么?除了机器码还有什么?它们是怎么存放的,是怎么组织的?
- #include<stdio.h> 是什么意思?把 stdio.h 包含进来意味着什么?C 语言库又是什么?它是怎么实现的?
- 不同的编译器和不同的硬件平台以及不同的操作系统,最终编译出来的结果是一样吗?为什么?
- Hello World 程序是怎么运行起来的?操作系统是怎么装载它的?它从哪儿开始执行,到哪儿结束?main 函数之前发生了什么?main 函数结束之后又发生了什么?
- 如果没有操作系统,Hello World 可以运行吗?如果要在一台没有操作系统的机器上运行 Hello World 需要什么?应该怎么实现?
- printf 是怎么实现的?它为什么可以有不定数量的参数?为什么它能够在终端上输出字符串?
- Hello World 程序在运行时,它在内存是什么样子的?
计算机的体系结构
- 计算机硬件的多如牛毛,其中三个部件最为关键:CPU、内存、IO控制芯片
- 北桥芯片:协调CPU、内存和高速的图形设备锁设计。其中高速的硬件设备连接北桥,低俗连接南桥。
- 对称多处理器(SMP)多CPU
- 一个处理器多核芯(多核处理器)
- 硬件提供应用程序的编程接口。目前我们编写驱动程序,由操作系统和硬件进行对接
操作系统
- 操作系统提供抽象的接口、管理硬件资源
- 应用程序以进程的方式在操作系统中运行,目前CPU的分配方式为抢占式(操作系统拥有主导权,可以强制收回进程占用的cpu资源)
程序使用物理地址的缺陷:
- 地址空间不隔离 程序间可以任意修改数据
- 内存使用效率低 大量数据换入换出
- 运行地址不稳定 每次运行时,从内存区域分配一个较大区域,空闲区域位置不确定
- 虚拟地址: 隔离物理地址和程序,虚拟地址映射到物理地址,可以隔离地址空间
- 内存分页:把地址空间人为地等分成固定大小的页。一般 4KB。把常用的数据和代码装载到内存中,把不常用的代码和数据保存在磁盘里,当需要用到的时候再把它从磁盘中取出来。保存也是页映射的目的之一,简单说就是可以设置每个页的权限属性,谁可以修改,谁可以访问。映射是依靠硬件支持的。MMU(Memory Management Unit),一般集成在 CPU 内部。
线程基础
线程组成: 线程ID、当前指令指针(PC)、寄存器集合和堆栈组成
时间片: 线程可以执行的一段时间
访问权限
私有
- 栈
- TLS
- 寄存器(包括PC寄存器) 公有
- 全局变量
- 堆
- 静态变量
- 代码
- 打开的文件
线程根据优先级进行调度: 频繁等待的线程称为IO密集型及线程,更容易拿到优先级
线程优先级改变的方式
- 用户指定优先级
- 根据进入等待状态的频繁程度提升或者降低优先级
- 长时间得不到执行而被提升优先级
抢占线程: 线程时间片用尽被强制进入ready状态,叫做抢占
不可抢占:不可被其他线程抢占
同步与锁
- 二元信号量:两种状态,占用、非占用
- 互斥量: 哪个线程获取,哪个线程释放
- 临界区:作用范围为本线程
- 读写锁
- 条件变量 初始值为N,完成减一
用户线程与内核线程是多对多的关系,防止一个线程阻塞影响其他线程