从CPU管理到进程的引入

2019-05-25 19:55:28 浏览数 (1)

为什么要管理CPU,这是因为在“上古时代”,CPU是计算机硬件之中最昂贵的资源。因此提高CPU利用率是很有必要的。我们知道只要给CPU的PC一个地址,CPU就能运行起来了,假设在运行一段时间后,需要一些I/O操作,而I/O操作(当年主要是连接打印机等)是很费时间的。这个时候的CPU是闲置的。而实际等着CPU去处理的程序有一大堆,这时候CPU资源是被浪费掉的。因此必须想办法提高CPU利用率。现在管理CPU是因为这样能更好的支持多个程序在单用户上进行,以及给用户良好的人机交互体验。

一个直观的想法就是在I/O等不需要占用CPU的操作执行时,让CPU去执行其他的程序。基于这个想法就诞生了:多道批处理程序。这样,当一个程序不需要占用CPU资源的时候,就切换到下一个程序去取指执行。这样在一个CPU上交替执行多个程序,这就是:并发。

假设现在有两个程序在内存中放着,分别称之为程序1和程序2。现在我们先执行程序1,执行一段时间后,程序1需要连接打印机进行打印操作,这个时候CPU就闲置下来了,此时我们切换到程序2执行。等到程序1执行完打印工作后,我们就从程序2切回程序1继续执行。实现切换程序是简单的,就是修改PC的值。通过修改PC,我们就可以实现切换执行程序的操作。但是有个问题需要解决,这就是切回程序1继续执行的时候,可能下一步的操作需要切换到程序2执行之前的一些处理结果。因此,需要将程序1的执行信息给保存起来,对于程序2也是如此。否则这样的切换是没有意义的,而且还可能导致程序出错。这时候我们需要一个概念,就是进程。

首先,我们都知道我们写的C语言代码,最后经编译器的预处理,编译,汇编,链接这些操作可以得到一个可执行文件。这个可执行文件,在Windows下就是后缀为exe的文件。我们双击这个文件,他就运行起来了。我们把这个运行起来的程序就称之为一个进程。所以当可执行文件静静的躺在磁盘里的时候它是“死的”,只是一个二进制文件。只有当把这个可执行文件映射到内存里的时候,它才是动态的。

为了保存一个进程的信息,引入了PCB(process control block)进程控制块来保存进程的信息。这样在一个CPU上执行多个进程就是多进程。但是在微观上来看,一次只能有一个进程在CPU上运行,其余的进程都是等待或者就绪状态。

需要注意的是,一个程序可以有多个进程。这些进程在内存中的不同映射。

每一个进程在操作系统内使用——进程控制块PCB来表示。进程控制块包含了一个特定进程的相关信息。一般而言,在操作系统中PCB的数目是一定的。操作系统通过PCB来感知进程的存在与否。一个PCB主要包含的主要信息列在了下表中。

进程调度:进程进入系统时,会被加到作业队列中,该队列包括系统中的所有进程。驻留在内存中的等待运行的进程加入就绪队列。对于计算机而言,每个设备都有自己的设备队列,需要使用该设备的进程都会在该设备的队列中等待设备空闲。例如磁盘队列。进程在其生命周期内会被不断在各种队列之中来回迁移。操作系统为了调度,必须按照某种方式来从队列中选择进程。这就需要调度程序。

上下文切换:把CPU切换到另一个进程需要保存原来进程的状态并装入新进程的保存状态。内核会将旧进程的关联状态保存到PCB中。上下文切换的复杂度和硬件紧密相关,例如有的处理器提供了寄存器组,这样就能避免过多的数据复制。

进程创建:在进程执行的过程中,父进程能通过系统调用创建子进程。当进程创建完毕后,有两种可能的执行:

  1. 父进程和子进程并发执行
  2. 子进程先执行,父进程后执行

新进程的地址空间也有两种可能:

  1. 子进程是父进程的复制品
  2. 子进程装入另一个程序进来

进程终止:当进程执行结束的时候,调用exit函数请求操作系统删除它。这时子进程返回数据到父进程。当然,在某些情形下也会出现终止,进程通过适当的系统调用能结束另一个进程。父进程终止子进程的原因很多。

进程协作:如果一个进程在执行的时候不影响其他进程,并且其他进程也不影响他。那么它就是独立进程。如果多个进程之间是有相互影响的,那么他们就是协作的。协作能带来一下好处:

  • 信息共享
  • 加快计算
  • 模块化
  • 方便

进程协作的一个典型问题是——生产者-消费者问题。

生产者进程产生信息,以供消费者进程消费。为了允许生产者进程和消费者进程能够并发执行,必须要有一个公共缓冲区来被生产者填充,被消费者使用。消费者不能提前消费,生产者也不能生产超过缓冲区的信息。缓冲区的设置可以借由进程通信或者是共享内存来解决。

0 人点赞