目录
一、 程序 & 进程
程序是静态的可执行文件 (exe) 。它是计算机指令的集合,以文件的形式存储在磁盘上;
进程是动态运行的一个可执行文件。躺在我们电脑桌面上的程序就是一个个的exe,当我们双击某个程序执行它的时候,该程序就运行起来,运行起来的程序就叫做一个进程。
🔊 静态->动态的过程
一个静态的exe是保存在磁盘中的。双击运行它时,操作系统将它加载到内存中,继而放入寄存器,最后由CPU执行该程序。程序动态执行,一个进程就此形成。
二、进程管理
多个进程之间并发/并行执行。
🔊 什么叫并发?并发与并行的区别是什么?
一个CPU核心只能执行一个进程,但多个进程都需要执行啊,所以为了让每个进程得到CPU的资源。操作系统需要调度各个进程,轮流切到CPU上执行。这个过程非常迅速,以至于我们感觉是多个进程在同时进行 -- 并发式的执行(宏观上同时进行,微观上轮流进行)
CPU上可能有多个核心,每个核心都可以跑一个进程。有可能在某一时刻,两个进程在两个CPU核心上同时执行。 -- 并行式的执行(宏观微观都是同时进行)
虽然有并发/并行两个概念,不过我们通常不会过分的区分他们俩,一般都说成并发编程
一个CPU核心只能执行一个单线程的进程,CPU数量少,进程多。要保证多个进程有条不紊的运行,就需要操作系统对进程进行管理。操作系统管理的依据就是程序控制块PCB。
PCB就是 为了管理进程 设计的 存储着进程信息 的数据结构。
🔊 怎么理解PCB ?
为了管理进程,操作系统必须对每个进程及其所做的事情进行清楚的描述。为此,操作系统使用PCB(进程描述符或进程控制块)这个数据结构来代表不同的实体,继而对其管理。
举个例子:老师对班级的学生进行管理,就会有一个花名册列出班级学生的姓名。除此之外,以后每次学生违纪表扬批评都可以记录在对应的学生的页码上。
1. PCB中的信息
进程的PCB中有很多信息,这里只列出了部分常见的:
- 进程的身份标识:pid等其他标识。便于认识当前运行的是哪个进程;
- 内存指针:指向进程的虚拟地址空间(用户空间)信息。操作系统需要将一些必要的数据(指令/数据)加载到内存中,内存指针就描述了该进程中指令/数据的位置;
- 文件描述符表:文件描述符表内部是顺序表结构,每打开一个文件,系统就会在进程文件描述符表中给这个文件分配一个表项。顺序表的每个元素就代表一个打开的文件,对应的数组下标就是“文件描述符” 。记录当前进程打开的文件信息;
- 优先级:进程相对于其他进程的调度优先级,优先级决定该进程进入到CPU的优先顺序;
- 状态:描述该进程当前的状态
- 记账信息:有些进程调度次数多执行时间长,有些进程调度次数少执行时间短。为了一碗水端平,PCB上就记录着每个进程以往在CPU上执行的时间/指令条数次数,便于合理安排各个进程轮流的执行操作;
- 进程的上下文信息:进程并发轮流到CPU上进行,存在着进程的切换,有时候可能一个进程的任务没执行完就被切换下场了。此时进程的上下文信息就记录CPU的所有寄存器中的值、进程的状态以及堆栈上的内容。当内核需要切换到另一个进程时,保存当前进程的所有状态,以便再次执行该进程时,能够恢复切换时的状态,继续执行。
操作系统根据PCB以及其中的信息,对各个进程进行资源分配,使之合理拿到CPU的资源...
2. PCB的结构
每一个单线程进程均有一个PCB。在创建进程时,建立PCB,伴随进程运行的全过程,直到进程撤消而撤消。操作系统有若干个进程就有若干个PCB,如果彼此分散还是不方便管理,于是操作系统又将若干个PCB串成了双向链表。
三、进程的状态&状态的转换
一个进程的生命周期可以分为一组状态,这些状态刻画了整个进程。常常能看到三态模型、五态模型,这都是操作系统中进程的状态模型。
1. 三态模型
- 就绪态(ready):进程具备运行条件(已分配到所需资源),等待系统分配 CPU 以便运行。
- 运行态(running):进程处于就绪状态被调度后,占有 CPU 正在运行。
- 阻塞态 / 等待态(wait):正在执行的进程由于某些事件(I/O请求,申请缓存区失败)而暂时无法运行,进程受到阻塞。缺少相应的资源,不具备运行条件。在满足运行条件后,又会进入就绪状态等待系统调用。
虽然宏观下多个进程看起来是同时进行的,但微观下多个进程轮流进行。为了一碗水端平,保证每个进程都可以公平调度:CPU 时间被划分为一段段的时间片,这些时间片再被轮流分配给各个进程。某个进程的时间片用完后这个进程就会进入就绪态,而其他被分配到时间片的进程就会进入运行态。
2. 五态模型
很多系统中都增加了新建态(new)和终止态(exit),形成五态模型。
- 创建状态(new):进程在创建时需要申请一个空白进程管理块,向其中填写控制和管理进程的信息,完成资源分配。如果创建工作无法完成,比如资源无法满足,就无法进入接下来的就绪状态,把此时进程所处的状态成为创建状态
- 终止状态(terminated):进程结束或出现错误或被系统终止,进入终止状态
四、虚拟地址与物理地址
1. 虚拟地址的由来
在早期的计算机中,是没有虚拟内存的概念的。我们要运行一个程序,会把程序全部装入内存,然后运行。但是当运行多个程序时,经常会出现以下问题:
- 内存空间不够且利用效率低
计算机发展过程初期,内存空间并没有现在这么大。如果很多的进程并发进行,每个进程就都需要一份物理空间。内存没那么大,物理空间稀缺,放不下太多的进程。当内存空间不足时,要将其他程序暂时拷贝到硬盘,然后将新的程序装入内存运行。由于大量的数据装入装出,内存使用效率会十分低下。
- 进程地址空间不隔离,不安全
如果每个进程都在内存有一份物理空间,由于进程可以直接访问物理内存,所以一个进程可以修改其他进程的内存数据,甚至修改内核地址空间中的数据。
( 我们知道多个进程是并发执行的,如果进程直接访问物理地址。假设我们打开了三个相同的计算机程序,都执行到某一步。比方说,用户在这三个程序的界面上分别输入了 10、100、1000,其对应的指令就是把用户输入的数字保存在内存中的某个地址中。前一个进程很有可能拿到另一个进程的物理地址,就容易发生冲突)
- 程序运行的地址不确定
因为内存地址是随机分配的,所以程序运行的地址也是不确定的。
因此操作系统创造了一个新的内存抽象,引入了一个新的内存模型,那就是虚拟地址空间...
2. 虚拟地址的作用
操作系统会给每个进程分配一个虚拟地址空间(vitural address),并且独立于其他进程的地址空间。每个进程包含的栈、堆、代码段这些都会从这个地址空间中被分配一个地址,这个地址就被称为虚拟地址。底层指令写入的地址也是虚拟地址。
有了虚拟地址空间,进程就有了一个重要的特性:隔离性
一个进程的进行一般不会影响到另一个进程,比如一个进程崩溃也不会影响到另一个进程。
有了虚拟地址空间后,CPU可以用过MMU(MMU内存管理单元)将需要用到的虚拟地址转换成合适的物理地址,转换过程称为 地址翻译/地址转换。
一个系统的进程这么多,虚拟地址的空间加到一起,比物理内存大了怎么办?
① 同一时刻执行的进程不多;
② 即使同一时刻有好几个进程都在运行,这些进程也不是同时将所有虚拟地址空间的对应的物理内存使用上了。物理内存只需要将真实使用的这部分内存数据表示出来