操作系统-并发控制原理及其实现

  首先我们要明白“皮之不存,毛将焉附”的道理,计算机系统是硬件与系统软件完美结合的一个有机整体。因此在学习这一部分时,特别是学习中断控制原理和系统凋用等内容时,要联系计算机组成原理的知识,这样才能对整个系统了解。

一、程序和进程

  进程(process)这一术语 ,最初是在麻省理工学院(MIT)开发的MULTICS;系统以及IBM公司开发的CTSS/360系统中提出,时间是60年代初期。自那时起,进程已成为现代操作系统中最核心的概念之一。因为,操作系统的某本控制原理都是围绕进程展开的。但是,进程控制的复杂性是由操作系统的并发机制引起的。 而目前经常使用的几乎所有操作系统都支持并行或并发机制,我们先介绍并发控制,并以多道程序作为问题的切人点来引出进程的定义。

  注:这里读者可能还不太理解进程到底是怎么回事?我们先把它记在心里,回过头再来看遍。

1.1  并发控制

  在支持多道程序环境的通用操作系统中 ,允许一个或若十个进程在系统中并发执行, 但由于系统硬件资源的有限性, 使得并发执行的若干进程之间会出现竞争系统有限软硬件资源的现象。 这些资源包括处理器内存I/0设备以及数据库等, 这就需要操作系统来协调和优化分配系统共享资源。 特别是在单处理器系统中,任一时刻 CPU 只能运行一个进程, 而其他进程只能是等待 CPU 或其他资源。为了公平合理地对待所有进程, 内核为每个进程分配一小段时间一小段时间被称为时间片。 一旦正在被运行进程的时间片用完, CPU 就立即被切换去执行另一个等待运行的就绪进程。由于 CPU 的运行速度很快, 造成若干个进程同时在运行的一 种虚拟假像。 这就是多道程序的并发控制。

1.1.1  多道程序设计与分时共享

  如上所述 ,操作系统的功能是管理系统资源,以便为用户程序(应用程序)提供一个可执行环境。然而,对于初学者来说。操作系统却是以一种复杂的令人难以琢磨的方式运行。 追根溯底 ,还要从计算机系统的硬件资源讲起。

  在操作系统管理的硬件资源中,根据其工作速度可分为两大类。一类是组成计算机主要功能部件的处理器CPU、高速缓存、内存以及I/O接口;而另一类则是外围设备,又叫I/O设备。包括:键盘显示器打印机鼠标软驱硬驱光驱网络通信设备等。 在这两类硬件资源中, 由于构成的原材料及工作性质的不同,其运行速度有着天壤之别,处理器 CPU 、高速缓存以及内存等是由晶体半导体材料所组成;因此工作时, 其电信号的传播速度几乎为光速。而外围设备大都含有机械装置,显然依赖按键、齿轮以及杠杆传递信息,其运行速度无法与接近光速的电子器件相比。

  多道程序设计就是将内存分成若干个部分,每—部分存放不同程序的执行代码。当其中—个进程需要等待外设操作完成时,CPU可以保存当前进程的所有信息,选择另—个进程来运行,但是如果多道程序中的一道是大型科学计算,在运行的数小时里不需要外设操作,那么内存中的其他若干道程序将只能等待,而拥有这些程序的用户却希望能及时得到响应。 这种需求导致了分时系统的出现。在分时系统中,系统为内存中的每一个进程分配一个时间片,当正在执行程序的时间片用完后,操作系统将把处理机分配给另一个就绪进程。对于单机系统(一个 CPU), 在某一时刻只能运行一个进程的一条指令,但是由于CPU的工作速度比人的反应快几百万倍甚至几亿倍。因此,虽然CPU在进程之间快速切换,而人的感觉却是机器在同时执行多个程序。 这就是所谓的多道程序的分时共享,这种工作方式叫做并发机制。 当然,并发控制并非不用付出代价。当操作系统从一个进程切换到另一个进程时,也要使用CPU。因此并发机制首先要保证并发设计所带来的效率要抵过由于进程切换所带来的额外开销。

  并发是指在同一时间间隔内对资源的共享。即内存中的多个进程分时共享CPU、内存以及 I/O设备。显然,并发机制可以高效地使用CPU,协调高速CPU与慢速外设的矛盾。但是处理并发并不容易。在内存中同时驻留多个进程需要特殊的硬件以及软件的配合对其进行保护,以免各个进程的信息被窃取并遭到攻击。因此,现代操作系统的一个重要内容就是管理计算机的并发操作。

  操作系统中的许多迫切需要解决与研究的问题都是由并发机制而引起的。例如:围绕若 “竞争条件”而引入了临界区、原子操作、同步与互斥、锁变量,等等。因此,并发控制向程序设计人员提出了新的重要的学习目标。因为并发程序并不总是按照预期的结果运行。因此调试并发程序是一件棘手的事,而且并发程序典型的不易解决的毛病是,一个并发程序编译运行后,大多数情况下运行结果都很好,但是极少数的情况下它会莫名其妙地失败,而且无法找到原因。

1.1.2  并发控制的硬件支持

  操作系统要实现并发控制的设计目标,离不开硬件平台的支持。因为内核必须使用中断机制和硬件上下文切换机制,才能实现多道程序的分时共享,否则CPU无法知道某个进程的时间片已经耗尽,需要调用另一个进程运行。另外,还要考虑CPU执行进程切换的时间开销要尽可能的小,如果CPU执行进程切换的时间开销太大,则多道程序设计将失去意义。

  现代计算机都有一个叫做定时器和计数器的硬时钟设备,而用于定时中断的时间测量设备,叫做可编程间隔定时器。在IBM代机上一般使用8254CMOS芯片作为硬时钟设备,操作系统可对其进行编程,编程后它可以按照人的意愿以一定的时间间隔向CPU发出定时中断。也就是当间隔定时器到时时,它便产生一个中断请求,请求CPU去执行定时器中断服务例程。该中断服务例程将控制器交给操作系统,由操作系统确认当前进程在CPU上已运行的时间,如果分配给它的时间片已经用完,操作系统将剥夺该进程的执行权,并按照一定的算法把它放置到就绪进程队列中,等待下一个运行的机会。

  为了实现分时共享,内核必须将时间片已经耗尽的当前进程挂起,然后从就绪队列中选择,一个具有较高优先权的进程投入运行这个过程称为进程切换,或叫任务切换、上下文切换

  在多道程序环境中虽然每个进程可以拥有属于自己的地址空间,但所有进程必须共享使用,CPU的各种寄存器。因此在恢复一个进程执行之前.内核必须将该进程在挂起时的寄存器数据再装人CPU的各个寄存器中才能继续运行。我们把进程恢复执行前必须装入寄存器的一组数据称为硬件上下文。这样可以节省进程切换为系统带来的额外时间开销,当然在具体实现进程切换时如果系统指标允许,也可以使用软件的方法进行上下文切换。Linux2.2以上版本就是如此。

1.2  进程的定义和特征

  在并发系统中,进程(process)是在由内核定义的数据结构上进行操作的一个计算活动。它是系统进行资源分配和调度的一个独立单位。进程是动态的、有生命周期的。内核可以创建一个进程,并由调度程序“调度”而运行。在请求I/O操作时被阻塞,当它完成自己的历史使命后,将由内核终止该进程使其消亡。

1.2.1  程序与进程

  程序这个术语是非常形象,非常具体的;它就是人们常说的“源程序”和“源代码”。例如C语言经典程序:

1 #include <stdio.h>
2 
3 int main(void)
4 {
5    printf("Hello World!\n");      
6    return 0;  
7 }

  用汇编语言编制的程序就是完成某一特定任务的一组指令的集合。 而C语言程序是面向过程的语言 , 组成该程序的语句比汇编指令容易理解 , 因为它和人类所习惯的表达方式比较接近。 只是运算符号以及语法有所不同。但无论用什么语言编制的程序, 都是为让计算机完成某一特定功能而编写的文本文件。 这些文本文件是不能直接在机器上运行的, 它们必须经过系统软件(包括编辑器和编译器)的输入并编译或汇编后,转换成二进制的可执行代码, 才是计算机可以识别的机器语言。 此时。程序就是一个包含二进制可执行代码文件的模块。 当内核把二进制的可执行代码装入内存后, 它由三部分组成:代码段、 数据段和堆栈段,线性地址的低地址字段是代码段 , 存放程序经编译后的可执行代码(程序文本)。 

  在操作系统中,代码段是只读的、不能修改,所以,代码段的长度是不会改变的。 在程序文本的上方是数据段,用来存放程序的变量 、字符串和其他数据。它分为初始化静态数据和未初始化静态数据 (BSS)。数据段的长度是可以改变的。程序可以修改其中的变量。许多程序在运行时需要动态分配内存。在UNIX中可以使用系统调用 malloc ()函数来获得。在数据区上方是堆栈段。 一般情况下, 堆栈段起始于虚拟地址空间的高端,栈向下方增长。当系统启动程序运行时,堆栈中存放有环境变量和命令行参数。程序的可执行代码调人内存后,这三部分统称为程序映像。 在虚拟地址空间 ,代码段 、数据段和堆栈段的地址空间是连续的。而在物理内存中,代码段、数据段和堆栈段的地址空间不一定是连续的。

  在内存中的程序映像运行之前,操作系统还要为其在内核的进程表项中分配一个被称为进程控制块的内核数据结构。同时要在该内核数据结构中加入程序运行时所需要的相应信息,其中最为重要的信息有:

• 指令指针:用以指示该进程正在执行的那条程序代码指令的地址。
• 进程的用户标识符。
• 进程的程序文本和数据区的存储器位置。
• 进程的状态。

  由此可以看出,进程映像使程序完全具备了在多道程序环境中运行的基本条件。因此,内核为程序映像分配了进程控制块后 ,程序映像便转化成为进程映像当调度程序调度该进程映像执行时,就是所谓的进程。进程控制块是形成进程的最为重要的内核数据结构, 它是内核控制进程的数据结构。因为系统内核是根据进程控制块中的信息对正在运行的程序实施控制,以便完成程序所要求的操作可以用类比的方法来说明程序与进程之间的区别:
  程序是一个项目在行动之前的计划书(或叫行动方案),而进程就是对该计划书的实施过程。 显然,计划书和计划书的实施过程存在着很大的差别。 因为,虽然计划书是计划实施过程中一个不可缺少的组成部分,但不是全部,在计划书的实施过程中, 除了计划书这个文本文件(程序)外 。还需要人力资源和物力资源以及相应的信息资源。比方说,盖一幢大楼。 光有人楼的设计方案(图纸)是不行的, 还必须要有施工办公室(或称为指挥控制部门,相当于CPU和操作系统)、负责调配人力资源和物力资源以及保证施工方案顺利进行的各种措施(信息资源)。 如果没有人力资源 、物力资源以及运行机制去实施设计方案,那么计划书上的大楼将永远是纸上的大楼。 但是计划书的实施过程也永远离不开计划书。 另外,在计划书实施过程的不同阶段,工程可能处于不同的状态,例如:由于等待建筑材料或者是由于缺乏劳动力而小得不停工,此时工程将处于等待状态;当各项条件具备时再继续施工,此时工程处于运行态,下面给出进程的抽象定义:

  定义 2.1 (I)   进程是一个多元组,P = (p, h, f, e, s) ,其中: P 代表进程; p是可执行程序代码程序数据堆栈;h和f分别是执行程序代码时所需要的硬件软件资源;硬件资源包括CPU特殊功能寄存器内存磁盘等;软件资源包括内核数据结构以及相关的所有信息资源; s代表进程运行期间的各种状态;e是程序运行期间需要的控制信息

  (2)  进程能够动态产生、运行,也有生命周期,能够被内核终止。

1.2.2  从并发机制理解进程

  以上是从进程的数据结构描述了进程与程序的区别。 程序映像变成进程映像的时刻也就意味着程序将被调度执行,这样一个新的进程使产生了。下面从并发机制来理解进程和程序的区别,在一个并发处理系统中,当代码装入内存之后,内核允许多个或多个进程来执行它。也就是说, 允许多个进程并发执行同一代码段。 这就相当于,在同时启动的全国各地的香格里拉大酒店的建筑下地上,可以使用完全相同的酒店建筑设计图纸 ,这个建筑设计图纸就是可以共享的程序代码。
  如果多个进程并发执行同一代码段,那么要允许各个进程按照其各自的情况在任何时间开始执行和结束执行。因此,在同一时刻, 毋个进程处在同一代码段的不同机器指令处执行(相当于几个建筑工地的进度不同)。为了使执行同一代码的多个进程之间的数据和进度相互独立,必须为每个进程设置一个指令指针,指示该进程下一步将执行哪条指令。同时,每个进程要有自己的数据段和堆栈段用来保存程序运行过程中用到的变量值。

  下面我们分析一个简短的循环打印的C语言程序,就可以进一步得明白程序与进程的差别:

1 int i;
2 for(i = 5; i > 0; i--)
3 {
4   printf("Value of i is %d:\n",i);
5 }

停电了,后面继续!!

猜你喜欢

转载自www.cnblogs.com/lemaden/p/10134472.html