1、进程的产生
早期问题:
在早期未配置OS的系统和单道批处理系统中,程序的执行方式是顺序执行,即在内存中仅仅装入一道用户程序,由它独占系统中的所有资源,只有在一个用户程序执行完成之后,才允许装入另一个程序并执行。这种当时浪费资源、系统运行效率低。
解决办法:OS+进程
计算机上所有可运行的软件,包括操作系统,被组织成若干顺序进程,简称进程。一个进程就是一个正在执行程序的实例,包括程序计数器、寄存器和变量的当前值。每个进程有他自己的虚拟CPU,实际上真正CPU在各进程之间来来回切换,这种快速的切换称作多道程序设计,在多道程序环境下,程序的执行属于并发执行。
2、进程的定义
(1)进程是程序的一次执行
(2)进程是一个程序及其数据在处理及顺序执行时所发生的活动。
(3)进程是具有独立功能的程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。
如果一个程序运行了两遍,则算两个进程。
3、进程的创建
简单的系统(eg:微波炉中的控制器),可能在系统启动之时,之后所需要的所有进程都已经存在了。通用系统中,需要用某种方法在运行时依照需要创建或撤销进程。进程的创建通常发生在一下情形:
(1)系统初始化
(2)正在运行的进程执行了创建进程的系统调用
(3)用户请求创建一个新进程
(4)一个批处理作业的初始化
设计一个后台进程接收电子邮件,这个进程在一天的大部分时间都在睡眠,但是当电子邮件到达时就突然被唤醒了。停留在后台诸如电子邮件、打印活动等的进程称为守护进程,当检测到特定的活动时,唤醒进程以便服务该请求。
除了在启动阶段创建进程之外,新的进程可以在启动之后创建。一个正在运行的进程进场发出系统调用,一边创建一个或多个新进程协助其工作。
比如,有大量的数据需要通过网络传输进来并进行处理。那么创建一个进程接收数据,并把数据放入共享缓冲区,让第二个进程取走数据并进行处理。在多处理机中,让每个进程在不同CPU上运行会使整个作业运行的更快。
大型机的批处理系统中,当操作系统认为有资源可运行另一个作业时,它就会创建一个新的进程,并且运行其输入队列中的下一个作业。
从技术上看,这些情形中,新进程的创建都是由一个已经存在的进程执行了一个用于创建进程的系统调用而创建的。这个进程所做的工作是:执行一个用来创建新进程的系统调用。这个系统调用通知操作系统创建一个新进程,并且直接或者间接地指定在该进程中运行程序。
4、进程终止
条件:
(1)正常退出(自愿的):多数进程是由于完成了他们的工作而终止。
(2)出错退出(自愿的):命令行程序收到一些错误的参数时,会给出一些错误的信息并结束运行。基于UI的程序通常会有提示性的对话框,并要求用户重试。
(3)严重错误(非自愿):程序中存在严重的错误。如执行非法指令、引用不存在的内存、除数是零等。
(4)被其他进程杀死(非自愿):某个进程执行一个系统调用通知操作系统杀死某个其他进程。
5、进程的层次结构
在某些系统中,当进程创建了另一个进程后,父进程和子进程就以某种形式继续保持关联。子进程自身可以创建更多的进程,组成一个进程的层次结构。进程只有一个父进程(但是可以有0个、1个多个子进程)。
6、进程的状态
尽管每个进程是一个独立的实体,有自己的程序计数器和内部状态,但是,进程之间需要相互作用。一个进程的输出结果可能作为另一个进程的输入。
例如:windows cmd:
type data data2 | findstr"x":使用type命令输出两个文件的内容,并将内容传递给findstr,findstr选择输入中包含“x”的那些行。
(1)运行(Running) 实际上占用了CPU
(2)就(Ready) 可运行,但是因为其他程序正在运行而暂时停止
(3)阻塞(Blocked) 除非某种外部事件发生,否则进程不能运行
阻塞和就绪是完全不同的,阻塞时程序自身固有的原因(等待输入),就绪是由于系统技术上的原因引起的(没占用CPU资源)
三种状态之间四种可能的转换关系:
当操作系统发现进程不能继续运行下去的时候,发生转换1。在某些系统中,进程可以执行一个诸如pause的系统调用来进入阻塞状态。
转换2、3是由进程调度程序引起的。进程调度程序是操作系统的一部分,进程甚至感觉不到调度程序的存在。系统认为一个正在运行的进程占用处理器的时间已经过长了,决定让其他进程使用CPU时,会发生转换2。在系统已经让其他进程都享有了他们应有的公平待遇,而重新轮到第一个进程在一次占用CPU运行时,会发生转换3。
调度程序的主要工作就是决定应当运行哪个程序、何时运行以及它应该运行多长时间
当进程等待的一个外部事件发生时(如输入),则发生转换4,如果此时没有其他进程运行,则立刻触发转换3,该进程便开始运行。否则该进程将处于就绪状态,等待CPU空闲并且轮到它运行。
7、进程的实现
为了实现进程模型,操作系统维护着一张表格(一个结构数组),叫进程表。每个进程占用一个进程表项。(这些项也叫进程控制块) 。该表项包含了进程状态的重要信息,包括程序计数器、堆栈指针、内存分配情况、所有打开的文件的状态、账号和调度信息,以及其他在进程由运行状态转到就绪状态或者阻塞状态时必须保存的信息,从而保证该进程随后能再次启动,就像从未被中断过一样。
一个进程在执行的过程中可能会被中断数千次,但关键是,每次中断后,被中断的进程都可以返回到与中断发生前完全相同的状态。