1. 基本知识
1. 计算机系统
1.1 计算机系统的硬件部分
计算机最主要的三个部件:CPU、内存、I/O控制芯片。
早期的计算机中CPU和内存频率基本一致,两者直接连在一根总线上,I/O设备频率较低,通过I/O控制器链接在总线上。
北桥:为协调CPU、内存和高速的图像设备,专门设计了一个高速的北桥芯片用于它们之间交换数据。北桥芯片的最高速度为133MHz。
南桥:用于处理低速设备之间数据交换
对称多处理器(SMP): 一台计算机多个CPU,多个CPU在系统中所处的地位和发挥的功能完全相同。多处理器应用场景最多的场合是商用的服务器和需要大量计算的环境。
多核处理器(Multi-core processor): 多个处理器之间共享缓存部件,只保留多个核心并且包装成一个处理器。实际上是SMP的简化版。
1.2 计算机系统的软件部分
系统软件: 一般将用于管理计算机本身的软件称之为系统软件。系统软件可分为两类:平台性的软件(包括操作系统内核、驱动程序、运行库等)、用于应用程序开发的软件(编译器、连接器)
计算机软件的体系结构: 硬件————>操作系统内核——(系统调用)——>运行库————(API)————>应用软件
接口: 计算机体系结构中各个层级之间需要相互通信,相互通信所需的协议,一般称之为接口。
API: 应用程序使用的接口是运行库提供的,这种接口称之为应用程序编程接口(API)
系统调用:运行库使用的操作系统提供的接口称为系统调用接口。系统调用的实现往往以 软件中断 的方式提供。
操作系统的功能: 提供抽象的接口 + 管理硬件资源
计算机的资源主要分为CPU、存储器和I/O设备。 为了充分利用硬件资源,操作系统发展出了很多不同的方式。
CPU利用率提升历程:单道程序 ——> 多道程序 ——> 分时系统 ——> 多任务系统
多任务系统: 操作系统接管了所有的硬件资源并且本身运行在受硬件保护的级别。所有应用程序都已进程的方式运行在比操作系统权限更低的级别,每个进程都有自己独立的地址空间,使得进程之间的地址空间相互隔离。CPU由操作系统统一进行分配,每个进程根据进程优先级的高低都有机会得到CPU,但是如果运行时间超过限制,操作系统会暂停该进程,将CPU分配给其他的进程。这种CPU的分配方式成为抢占式——操作系统可以强制剥夺CPU的资源并且分配给它认为目前最需要的进程。
在多任务系统中,操作系统相当于主控,控制着CPU应该由哪个进程使用。
操作系统作为硬件的上层,它是对硬件从管理和抽象。对于操作系统上层的运行库和应用程序来说,它们希望看到的是统一的硬件访问模式。硬件细节全部由操作系统中的硬件驱动程序来完成。驱动程序可以看成是操作系统的一部分,其往往和操作系统一样运行在特权级,但是它又和操作系统内核之间具有一定的独立性,使得驱动程序有比较好的灵活性。
多任务操作系统中,站在进程的角度来看,每个进程仿佛独占了CPU,不用考虑与其他进程分享CPU的事情。那么针对每个进程,内存是如何使用的呢?
程序对内存的使用方式发展过程:程序直接运行在物理内存上 ————> 虚拟地址
程序直接运行在物理地址上存在的问题: 地址空间不隔离、内存使用效率低、程序运行的地址不正确
地址空间是一种比较抽象的概念,可以理解为地址范围。
地址空间分为两种: 物理地址空间 + 虚拟地址空间
物理地址空间: 物理地址空间是实实在在存在的,存在于计算机中,可以理解为物理内存。
虚拟地址空间:虚拟地址空间是虚拟的,其实并不存在,每个进程都有自己独立的虚拟地址空间,从而做到了进程间地址空间的隔离。
分段(Segmentation): 把一段程序所需的内存空间大小的虚拟空间映射到某一个地址空间。其实就是将虚拟地址空间和物理地址空间做一对一映射。
分段解决了 进程间地址空间不隔离 和 程序运行的地址不正确 的问题,但是仍旧没有解决内存使用效率低的问题。
分页(Paging): 分页的基本方法是把地址空间人为地等分为固定大小的页,每页的大小由硬件决定,一般为4KB。程序在运行过程中只把部分页映射到内存中,其余保留在地盘中,等到需要时在映射到内存中。从而实现高效的使用内存。
虚拟内存的实现需要依靠硬件的支持,一般都是采用MMU(集成在CPU中)来进行页映射。
CPU ———虚拟地址———> MMU ————物理地址————> 物理内存
2. 线程
2.1 线程基础
线程是程序执行流的最小单元,一个标准的线程由线程ID、当前指令指针、寄存器集合和堆栈组成。各个线程之间共享程序的内存空间(代码段、数据段、堆)以及一些进程级的资源(打开文件、信号)。
每个线程都有单独的栈,同一个进程中的所有线程共享一个堆。
线程的访问非常自由,它可以访问进程内存中的所有数据,甚至包括其他线程的堆栈,但实际上线程也有自己的私有存储空间:栈(尽管并非完全无法被其他线程访问,但一般情况下认为是私有数据)、线程局部存储(TLS)、寄存器
线程在计算机上总是并发执行的,当线程数量小于处理器数量时,是真正的并发。
在线程调度过程中,线程通常拥有三种状态:就绪态、运行态、等待态
每个线程都有自己的线程优先级,操作系统根据线程优先级来决定执行哪一个线程
在优先级调度下,存在一种饿死的现象,即优先级低的线程迟迟得不到调度。为解决该问题,操作系统会为迟迟得不到执行的线程提升优先级。
线程优先级改变的三种方式: 用户执行优先级、根据进入等待状态的频繁程度提升或降低优先级、长时间得不到执行而被提升优先级
windows中有标准的线程和进程。但是在linux中,线程并不是一个通用的概念,linux将所有的执行体称为任务(Task),每一个任务概念上都类似于一个单线程的进程,具有内存空间、执行实体、文件资源等。Linux下不同的Task之间可以共享内存空间,因而在实际意义上,共享了内存空间 的多个任务构成了一个进程,而这些任务就成了进程中的线程。
linux下可以使用三种方法创建一个新的任务: fork 、 exec、 clone。
fork函数产生一个和当前进程完全一样的新进程,并和当前进程一样从fork函数里返回。其中本任务的fork返回新的pid,新任务的fork返回0。
fork产生新任务的速度非常快,因为fork并不复制原任务的内存空间,而是和原任务共享一个写时复制的内存空间。
写时复制:两个任务可以同时自由的读取内存,但是任意任务试图对内存进行修改时,内存就会复制一份提供给修改方单独使用。
2.2 线程安全
多线程同时访问一个共享数据时,可能造成很恶劣的后果。
为了避免多个线程同时读写同一个数据而产生不可预料的后果,我们要将各个线程对同一个数据的访问同步或采用原子操作。
同步:指一个线程访问数据未结束时,其他线程不得对同一个数据区进行访问。
同步最常见的方式是使用 锁。
锁是一种非强制机制,每一个线程在访问数据或资源前首相试图获取锁,并在访问结束之后释放锁。在锁已经被占用的时候试图获取锁,线程会等待,直到重新可用。
信号量:
互斥量:
临界区:
读写锁:
条件变量:
可重入:一个函数可重入指的是这个函数没有被执行完成,由于外部因素或内部调用,又一次进入该函数被执行。
一个函数被重入只有两种情况:多线程同时执行这个函数、函数自己调用自己。
可重入函数的特点:1. 不适用任何静态或全局非const变量 2. 不反悔任何静态或者全局的非const变量的指针 3. 仅依赖调用方提供的参数 4. 不依赖任何单个资源的锁 不调用任何不可重入函数。
可重入是并发安全的强力保障,一个可重入的函数可以在多线程环境下放心使用。
2.3 线程模型
用户态线程并不一定在操作系统内核里对应同等数量的内核线程。
用户态线程与内核态线程的对应关系: 一对一模型、多对一模型、多对多模型
一对一模型: 用户态线程与内核线程一致,并发性能好。一般直接使用API或者系统调用创建的线都是一对一的线程。
一对一模型缺点:用户态线程数量受限、上下文切换开销大,执行效率下降
多对一模型:多个用户态线程映射到一个内核态线程。
多对一模型的缺点: 一个用户态线程阻塞,那么所有的线程都将无法执行,内核态线程也会随之阻塞。处理器的增多对 多对一模型的线程性能不会有明显提升。
多对一模型的优点:上下文切换效率高、线程数量无限制
多对多模型:多对多模型结合了多对一和一对一模型的特点,将多个用户态线程映射到少数但不止一个内核线程上。
2. 静态链接
1. 程序构建
从源代码到可执行文件,中间一共由四个过程: 预编译、编译、汇编、链接。
1.1 预编译
预编译过程将源文件编译成后缀为.i(或者 .ii)的文件,在此过程中将源文件中以 “#”开始的预编译指令。
gcc -E test.cpp -o test.ii
预编译过程中对预编译指令的处理规则:
- 将所有的#define删除,且展开所有的宏定义。
- 处理所有条件预编译指令
- 处理#include 预编译指令,将被包含的文件插入到该预编译指令的位置。
- 删除所有的注释
- 添加行号和文件名标识
- 保留所有#pragma编译指令,编译时需要使用。
1.2 编译
编译过程就是将预编译之后的文件进行一系列的分析及优化后生成相应的汇编代码文件。编译过程一般分为6步: 扫描、语法分析、语义分析、源代码优化、代码生成、目标代码优化。
gcc -S test.ii -o test.s
对于C语言来说,预编译和编译的程序是ccl,C++语言的预编译和编译的程序是cclplus。其实gcc命令是ccl等后台程序的包装,它会根据输出入参数的不同选择调用哪些程序
1.3 汇编
汇编过程是将汇编文件转换成由机器指令构成的目标文件的过程。
gcc -c test.s -o test.o
1.4 链接
链接过程是将多个目标文件和库文件连接在一起,生成可执行文件的过程。
重定位:重新计算各个目标地址的过程称之为重定位(Relation)。</
最低0.47元/天 解锁文章
490

被折叠的 条评论
为什么被折叠?



