程序和进程之间的关系可以用一句话明确的概括,即“进程是一种程序的执行机制”。
这里所谓机制就是有配套措施的通行性的做法;而所谓“一种”呢,也就是说还有其他的执行机制。
在计算机的发展历程中,最原始的ENIAC不需要操作系统,后来引入了最简单的单道批处理操作系统,这时的程序是一个一个依次执行,执行完了一个才轮到下一个。对于这种情况自然也不需要引入进程的概念。
只有发展到了多用户多任务操作系统阶段,有了并发的需求,才需要对程序的整个执行过程进行有效的描述和管理。抽象出进程的概念,我们有了描述程序的执行过程的手段,也就有了干预和管理程序执行的手段。
而我们要对进程这一概念建立起一个较为清晰完整的概念,则有必要进行以下三方面内容的讨论:
1.进程、程序和线程这三个概念的区别和联系
2.进程如何对程序进行有效的描述
3.操作系统如何通过“进程控制块”描述进程
1.进程和程序
第一个问题,进程和程序:程序这个概念比较简单,它就是机器代码指令和数据的集合,就是存在于磁盘的可执行映像或者源代码。这是一个静态的概念,也就是说我们能找到它,并能完整的掌握它。
而进程则要复杂的多,首先它包含机器指令和数据,但又不限于此,否则就和程序的概念完全一样了。而它与程序的区别在哪里呢?这就需要回顾引入进程的目的。我们说进程的引入是为了对程序的执行过程进行描述。而程序执行时有什么问题呢?
程序的执行至少会涉及到两方面的内容:
一个问题是程序要被执行,第一步就是要加载到内存中,而涉及到内存就涉及到内存寻址,内存分配,内存回收等一系列的问题,这一系列与内存相关的问题再和程序的执行联系起来,就是所谓的进程空间分配与管理的问题。
另一个问题是程序执行过程中,会打开文件,会链接外部设备,这些文件和设备的状态需要记录;程序的执行还会遇到诸如中断处理,函数调用等情况,这时候就需要使用堆栈保存现场。这些方面的问题,我们称之为进程上下文的问题。
综合上面的问题,我们可以得出程序有如下三个方面的内容:
1.一段可执行的程序
2.程序所需要的相关数据(变量,工作空间等)
3.程序的执行上下文(进程状态)
同时,我们可以先在这里提出由于进程概念的提出,我们很自然地发展出以下两种机制,使得通过进程对多道程序的并发处理变得有序,有效并且简单。
一个是虚拟处理器机制,它本质上通过进程调度,使得进程感觉到自己在独占CPU;
另一个是虚拟内存机制,在分配和管理内存是,让进程感觉自己在独享内存。
前面讲过那么多,大家可能会得出印象,进程难以捉摸。进程相对于程序这个概念来说确实复杂了许多,具有分散性和动态性的特点。但并不意味着,我们不能对它建立起一个直观具体的理解。事实上,我们可以通过进程映像建立起对进程直观的感受。
所谓进程映像就是某个时刻进程的内容。
下面就是一个典型的进程映像。
图 1. 一个典型的进程映像
在Linux中,另一个需要进行区分的概念是内核线程。所谓内核线程就是在内核态下创建、独立执行的一个内核函数,这种内核函数周期性运行以执行一些重要的系统任务(比方说磁盘高速缓存的刷新,网络连接的维护,页面的换入换出等)。内核线程具有下面三个特点:
1.每个内核线程执行一个单独指定的内核函数
2.只运行在内核态