勇敢心资源网

当前位置:首页 > 百科 / 正文

进程模型

(2020-02-28 03:09:11) 百科
进程模型

进程模型

在进程模型中,计算机上所有可运行的软体,通常也包括作业系统,被组织成若干顺序进程(sequential process),简称进程(process)。作业系统中最核心的概念是进程, 进程也是并发程式设计中的一个最重要、 最基本的概念。进程是一个动态的过程, 即进程有生命周期, 它拥有资源, 是程式的执行过程, 其状态是变化的。 Windows、 unix和Linux是目前最流行的几个作业系统。

基本介绍

  • 中文名:进程模型
  • 外文名:process model
  • 典例:Windows、 unix和Linux
  • 学科:计算机原理
  • 相关概念:进程
  • 区别概念:程式

运行原理

一个进程就是一个正在执行程式的实例,包括程式计数器、暂存器和变数的当前值。从概念上说,每个进程拥有它自己的虚拟CPU。当然,实际上真正的CPU在各进程之间来回切换。但为了理解这种系统,考虑在(伪)并行情况下运行的进程集,要比我们试图跟蹤CPU如何在程式间来回切换简单得多。正如我们所看到的,这种快速的切换称作多道程式设计。
在图中a我们看到,在一台多道程式计算机的记忆体中有4道程式。在图中b,这4道程式被抽象为4个各自拥有自己控制流程(即每个程式自己的逻辑程式计数器)的进程,并且每个程式都独立地运行。当然,实际上只有一个物理程式计数器,所以在每个程式运行时,它的逻辑程式计数器被装入实际的程式计数器中。当该程式执行结束(或暂停执行)时,物理程式计数器被保存在记忆体中该进程的逻辑程式计数器中。在图中c我们看到,在观察足够长的一段时间后,所有的进程都运行了,但在任何一个给定的瞬间仅有一个进程真正在运行。
在此,我们假设只有一个CPU。然而,逐渐这个假设就不为真了,因为新的晶片经常是多核的,包含2个、4个或更多的CPU。但是在现在,一次只考虑一个CPU会更简单一些。因此,当我们说一个CPU只能真正一次运行一个进程的时候,即使有2个核(或CPU),每一个核也只能一次运行一个进程。
进程模型
由于CPU在各进程之间来回快速切换,所以每个进程执行其运算的速度是不确定的。而且当同一进程再次运行时,其运算速度通常也不可再现。所以,在对进程编程时决不能对时序做任何确定的假设。例如,考虑一个I/O进程,它用流式磁带机恢复备份的档案,它执行一个10 000次的空循环以等待磁带机达到正常速度,然后发出命令读取第一个记录。如果CPU决定在空循环期间切换到其他进程,则磁带机进程可能在第一条记录通过磁头之后还未被再次运行。当一个进程具有此类严格的实时要求时,也就是一些特定事件一定要在所指定的若干毫秒内发生,那幺必须採取特殊措施以保证它们一定在这段时间中发生。然而,通常大多数进程并不受CPU多道程式设计或其他进程相对速度的影响。
值得注意的是,如果一个程式运行了两遍,则算作两个进程。例如,我们可能经常两次去启动同一个字处理软体,或在有两个可用的印表机的情况下同时列印两个档案。像“两个进程恰好运行同一个程式”这样的事实其实无关紧要,因为它们是不同的进程。作业系统能够使它们共享代码,因此只有一个副本放在记忆体中,但那只是一个技术性的细节,不会改变有两个进程正在运行的概念。

区别理解

进程和程式间的区别是很微妙的,但非常重要。用一个比喻可以使我们更容易理解这一点。想像一位有一手好厨艺的计算机科学家正在为他的女儿烘製生日蛋糕。他有做生日蛋糕的食谱,厨房里有所需的原料:麵粉、鸡蛋、糖、香草汁等。在这个比喻中,做蛋糕的食谱就是程式(即用适当形式描述的算法),计算机科学家就是处理器(CPU),而做蛋糕的各种原料就是输入数据。进程就是厨师阅读食谱、取来各种原料以及烘製蛋糕等一系列动作的总和。
现在假设计算机科学家的儿子哭着跑了进来,说他的头被一只蜜蜂蛰了。计算机科学家就记录下他照着食谱做到哪儿了(保存进程的当前状态),然后拿出一本急救手册,按照其中的指示处理蛰伤。这里,我们看到处理机从一个进程(做蛋糕)切换到另一个高优先权的进程(实施医疗救治),每个进程拥有各自的程式(食谱和急救手册)。当蜜蜂螫伤处理完之后,这位计算机科学家又回来做蛋糕,从他离开时的那一步继续做下去。
这里的关键思想是:一个进程是某种类型的一个活动,它有程式、输入、输出以及状态。单个处理器可以被若干进程共享,它使用某种调度算法决定何时停止一个进程的工作,并转而为另一个进程提供服务。

具体模型介绍

Windows、 unix和Linux是目前最流行的几个作业系统, 由于Linux和unix有很多的相似性, 这里仅分析Windows和Linux作业系统中的进程模型。
Linux进程模型
1.1 Linux进程描述符
为了管理进程,核心必须对每个进程所做的事情进行清楚的描述,这正是进程描述符的功能。进程描述符都是task_struct类型结构,它的栏位包含了与一个进程相关的所有信息。进程描述符包含了进程的所有信息 。task_struct是一个非常複杂的结构 。这里重点分析其包含的信息:
进程状态 (Stak);
进程调度信息 (SchedulingInfoMh);
各种知识符 (Identifiers);
进程通信有关信息 (IPC, Inter_Process Com-
munication);
时间和定时器信息 (Times and Timers);
进程连结信息 (Links);
档案系统信息 (File System);
虚拟记忆体信息 (Virtual Memory);
页面管理信息 (page);
对称多处理器 (SMP) 信息;
和处理器相关的环境 (上下文) 信息 (Pro-cessor Specific Context)。
下面对task_struct结构进行描述:
(1) 进程状态
进程模型
进程描述符中的state栏位描述了进程当前所处的状态。它由一组标誌组成,其中每个标誌描述一种可能的进程状态。下面是可能的6种状态:
① 可运行状态
进程要幺在CPU上执行,要幺準备执行。正在运行的进程就是当前进程 (由current所指向的进程),而準备运行的进程只要得到CPU就可以运行,CPU是这些进程唯一等待的系统资源。
② 可中断的等待状态
进程被挂起 (睡眠),直到某个条件变为真。
③ 不可中断的等待状态
与可中断的等待状态类似, 但有一点不同,把信号传递到睡眠进程不能改变它的状态。
④ 暂停状态
进程的执行被暂停。通常当进程接收到SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU信号后就处于这种状态。
⑤ 跟蹤状态
进程的执行已由debugger程式暂停。
⑥ 僵死状态
进程的执行被终止,但在发布wait4 () 系统调用前, 在进程表中仍然有它的任务结构。
(2) 进程调度信息
调度程式利用这部分信息决定系统中哪个进程最应该运行,并结合进程的状态信息保证系统运转的公平和高效。这一部分信息通常包括进程的类别 (普通进程还是实时进程)、 进程的优先权等。
(3) 标识符
Linux作业系统中允许用户使用一个叫做进程标识符process ID (或PID) 的数来标誌进程,PID存放在进程描述符的pid栏位中。PID被顺序编号,新创建进程的PID通常是前一个进程的PID加1。不过PID有一个上限值,当核心使用的PID达到这个上限值的时候就必须开始循环使用已闲置的小PID号。
(4) 进程通信有关信息
为了使进程能在同一项任务上协调工作,进程之间必须能进行通信即交流数据。Linux支持多种不同形式的通信机制。它包含如下域:
spinlock_t sigmask_lock: 信号掩码的自旋锁
long blocked: 信号掩码
struct signal *sig: 信号处理函式
struct sem_undo *semundo: 为避免死锁而在信号量上设定的取消操作
struct sem_queue *semsleeping: 与信号量操作相关的等待伫列
(5) 进程连结信息
程式创建的进程具有父/子关係。如果一个进程创建多个子程式时,则子进程之间具有兄弟关係。
(6) 时间和定时器信息
一个进程从创建到终止叫做该进程的生存期。进程在其生存期内使用CPU的时间,核心都要对其进行记录,以便进行统计、计费等有关操作。进程耗费CPU的时间由两部分组成:一是用户模式 (或称用户态) 下耗费的时间、一是在系统模式 (或称为系统态) 下耗费的时间。每个时钟滴答,也就是每个时钟中断,核心都要更新当前进程耗费CPU的时间信息。进程有3种类型的定时器:实时定时器、虚拟定时器和概况定时器。这3种定时器的特徵共有3个:到期时间、定时间隔和要触发的事件。到期时间就是定时器到什幺时候完成定时操作,从而触发相应的事件;定时间隔就是两次定时操作的时间间隔,它决定了定时操作是否继续进行。如果定时间隔大于o,则在定时器到期时,该定时器的到期时间被重新赋值,以使定时操作能继续进行下去,直到进程结束或停止用定时器,只不过对不同的定时器,到期时间的重新赋值操作是不同的。实时定时器不管其所属的进程是否运行都要更新,所以,时钟中断来临时,系统中所有进程的实时定时器都要被更新,如果有多个进程的实时定时器到期,则核心要一一处理这些定时器所触发的事件。而虚拟定时器和概况定时器只在进程运行时更新,所以,时钟中断来临时,只有当前进程的概况定时器得到更新,如果当前进程运行于用户态,则其虚拟定时器也会得到更新。
(7) 档案系统信息
进程可以打开或关闭档案,档案属于系统资源,Linux核心要对进程使用档案的情况进行记录。task_struct结构中有两个数据结构用于描述进程与档案相关的信息。其中,fs_struct中描述了两个vFs索引节点 (vFS inode),这两个索引节点叫做root和pwd,分别指向进程的可执行映像所对应的根目录 (Home Directory) 和当前目录或工作目录。file_struct结构记录了过程打开的档案的描述符 (Descrlptor),
(8) 虚拟记忆体信息
除了核心执行绪,每个进程都拥有自己的地址空间 (也叫虚拟空间),用mm_struct来描述。其记忆体信息如下:
struct mm_struct *mm: 描述进程的地址空间
struct mm_struct *active_mm: 核心执行绪所借用的地址空间
(9) 页面管理信息
当物理记忆体不足时,Linux记忆体管理子系统需要把记忆体中的部分页面交换到外存,其交换是以页为单位的。
(10) 对称多处理机
与对称多处理机相关的域如下:
int has_cpu: 进程当前是否拥有CPU
int processor: 进程当前正在使用的CPU
int lock_depth: 上下文切换时核心锁的深度
(11) 和处理器相关的环境信息
进程作为一个执行环境的综合,当系统调度某个进程执行, 即为该进程建立完整的环境时,处理器的暂存器、堆叠等是必不可少的。因为不同的处理器对内部暂存器和堆叠的定义不尽相同,所以叫做 “和处理器相关的环境”,也叫做“处理机状态”。当进程暂时停止运行时,处理机状态必须保存在进程的task_struct结构中,当进程被调度重新运行时再从中恢复这些环境,也就是恢复这些暂存器和堆叠的值。
处理机信息的定义形式为struct thread_struct*tss: 任务切换状态
1.2 Linux进程描述符处理
进程是动态实体,其生命周期範围从几毫秒到几个月。 因此,核心必须能同时处理很多进程,并把进程描述符存放在动态记忆体中。Linux把两个不同的数据结构紧凑地放在一个单独为进程分配的存储区域内:一个是核心态的进程堆叠,另一个是紧挨进程描述符的小数据结构thread_info,叫做执行绪描述符,这块存储区域的大小通常为8192个位元组 (两个页框)。核心使用alloc_thread_info和free_thread_info宏分配和释放存储thread_info结构和核心的记忆体区。
1.3 进程鍊表
进程鍊表把所有的进程的描述符连结起来。每个task_struct结构都包含一个list_head类型的tasks栏位,这个类型 的prev和next栏位分别指向前面和后面的task_struct元素。进程鍊表的头是init_task描述符,它是所谓的0进程(process 0) 或swapper进程的进程描述符。init_task的tasks.prev栏位指向鍊表中最后插入的进程描述符的tasks栏位。当核心寻找一个新进程在CPU上运行时, 必须只考虑可运行进程 (即处在TASK_RUNNING状
态的进程)。Linux2.6实现的运行伫列建立多个可运行进程鍊表,每种进程优先权对应一个不同的鍊表,其目的是让调度程式能在固定的时间内选出 “最佳” 可运行进程,与伫列中可运行的进程数无关。每个task_struct描述符包含一个list_head类型的栏位run_list。这样,核心就必须为系统中每个运行伫列保存大量的数据,不过运行伫列的
主要数据结构还是组成运行伫列的进程描述符鍊表,所有这些鍊表都由一个单独的prio_array_t数据结构来实现。
Windows进程模型

2.1 Windows进程的特点
Windows进程设计的目标是对多种作业系统环境提供支持。不同作业系统环境支持的进程在很多方面都是不同的,包括:
进程模型
◇ 进程如何命名
◇ 进程中是否提供执行绪
◇ 进程如何表示
◇ 如何保护进程资源
◇ 进程间的通信和同步使用什幺机制
◇ 进程之间如何联繫
因此,Windows核心所提供的进程结构和服务是相当简单和通用的,同时允许每个OS子系统模拟某种特定的进程结构和功能。Windows进程的重要特点如下:
◇ Windows进程作为对象实现
◇ 一个可执行的进程可能含有一个或多个执行绪
◇ 进程对象和执行绪对象都具有内置的同步能力
图4显示了进程与它所控制或使用的资源相关联的方式。每个进程都被指定一个安全访问标誌,称为进程的基本标誌。当用户初次登入时,Windows会创建一个包括用户安全ID的访问标誌。每个由用户创建的进程或代表用户运行的进程都有该访问标誌的一个副本。Windows使用这个标誌,使得用户可以访问受保护的对象,或者在系统上和受保护的对象上执行限定功能。访问标誌控制该进程是否可以改变它自己的属性,在这种情况下,该进程没有已打开的自身访问标誌的句柄。如果进程试图打开这样的一个句柄,则安全系统确定是否允许这样做,即确定该进程是否可以改变自己的属性。与进程相关的还有定义当前分派给该进程的虚拟地址空间的一系列块。进程不能直接修改这些结构,而必须依赖于虚拟存储管理器,它为进程提供了记忆体分配任务。进程还包括一个对象表, 表中有该进程知道的其他对象的句柄。对象中包含的每个执行绪都有一个句柄。对象句柄即对象标识符,当一个进程通过名称创建或打开一个对象时,它会接收到一个句柄,此后通过此句柄来访问该对象。对象句柄实际上是一个索引,指向与进程相关的句柄表中的表项。
2.2 Windows进程的组成
从最高抽象层次来看, Windows有以下几个方面组成:
◇ 一个私有的虚拟地址空间
◇ 一个可执行的程式: 定义了代码和数据,并被映射到进程的虚拟地址空间
◇ 一个已经打开句柄的列表: 指向各种资源,比如信号量、档案,该进程的所有执行绪都可访问这些系统资源
◇ 一个被称为访问令牌的安全环境: 标识与该进程关联的用户、 安全组和特权
◇ 一个被称为进程ID的唯一标识
◇ 至少一个执行执行绪
2.3 Windows进程的关键数据结构
Windows进程的数据结构主要有以下几块:
◇ 执行体进程块 (EPROCESS, Executive Process Block):执行体进程对象的对象体,包括进程ID、 父进程ID、程式名、进程优先权、记忆体管理信息、设备映像等。
◇ 核心进程块 (KPROCESS, Kernel Process Block):核心进程对象的对象体,又称PCB,包括执行绪调度时需要的信息,如进程状态、执行绪时间片等。
◇ 进程环境块 (PEB, Process Environment Block):包括用户态代码需要和修改的信息。
◇ Windows环境子系统核心态部件win32k.sys为每个进程建立的进程信息数据结构WIN32KPROCESS。
◇ Windows环境子系统进程csrss (用户态空间) 为每个进程建立的进程信息数据结构。每个Windows进程用一个对象表示。每个进程由许多属性定义,并且封装了它可以执行的许多行为或服务。一个进程在收到相应的讯息后将执行一个服务,调用这类服务的唯一方法是给提供该服务的进程对象传送讯息。当Windows创建一个进程后,它使用为Windows进程定义的、用做模板的对象类或类型来产生一个新的对象实例。并且在创建对象时,赋予其属性值。下面简单给出进程对象中每个对象属性的定义。
◇ 进程ID: 为作业系统标誌该进程的惟一的值
◇ 安全描述符: 描述创建了对象、可以访问或使用该对象以及不允许访问该对象的用户ID标誌
◇ 基本优先权: 进程中执行绪的基準执行优先权
◇ 默认处理器关联: 可以运行进程中执行绪的默认处理器集合
◇ 定额限制: 已分页的和未分页的系统记忆体的最大值、分页档案空间的最大值、用户进程可以使用处理器时间的最大值
◇ 执行时间: 进程中所有执行绪已执行的时间总量
◇ I/O计数器: 记录进程中执行绪已经执行的I/O操作的数量和类型的变数
◇ VM操作计数器: 记录进程中执行绪已经执行的虚拟记忆体操作的数量和类型的变数
◇ 异常/调试连线埠: 当进程中的一个执行绪引发异常时,用于进程管理器传送讯息的进程间通信通道
◇ 退出状态: 进程终止的原因一个Windows进程必须至少包含一个执行执行绪,该执行绪可能会创建别的执行绪。在Windows作业系统中,进程是资源分配的最小单位,而执行绪则是作业系统调度的最小单位。
Windows执行绪有六种状态, 以下分别予以介绍:
① 就绪态:可以被调度执行。微核心分派器跟蹤所有就绪执行绪,并按优先权顺序进行调度。
② 备用态:备用执行绪已经被选择下一次在一个特定的处理器上运行。该执行绪在这个状态等待,直到那个处理器可用。如果备用执行绪的优先权足够高,正在那个处理器上运行的执行绪可能被这个备用执行绪抢占。否则,该备用执行绪要等到正在运行的执行绪被阻塞或结束其时间片。
③ 运行态:一旦微核心处理执行绪或进程切换,备用执行绪将进入运行状态并开始执行,执行过程一直持续到被抢占、时间片期满、被阻塞或终止。在前两种情况下,它将回到就绪态。
④ 等待态:当执行绪被一个事件 (如阻塞、为了同步自愿等待) 或者一个环境子系统指引它把自身挂起时,该执行绪进入等待状态。当等待的条件满足时,如果它的所有资源都可用,则执行绪转到就绪态。
⑤ 过渡态:一个执行绪在等待后,如果準备好运行但资源不可用时,进入该状态。例如,一个执行绪的栈被换出存储器。当该资源可用时,执行绪进入就绪态。
⑥ 终止态:一个执行绪可以被自己或者被另一个执行绪终止,或者当它的父进程终止时终止。一旦完成了清理工作,该执行绪从系统中移出,或者被执行体保留,供以后重新初始化。
Windows进程和Linux进程比较
Linux 和 Windows 系统的进程结构都相当複杂。在Linux里,只有进程的概念,但在WIN32里却还有一个 “执行绪” 的概念,那幺Linux和WIN32在这里究竟有着什幺区别呢?在WIN32里,“进程” 是指一个程式,而 “执行绪” 是一个 “进程”里的一个执行 “线索”。从核心上讲,WIN32的多进程与Linux并无多大的区别,在WIN32里的执行绪才相当于Linux的进程,是一个实际正在执行的代码。但是,WIN32里同一个进程里各个执行绪之间是共享数据段的。这才是与Linux的进程最大的不同。在WIN32下,使用CreateThread函式创建执行绪,与Linux下创建进程不同,WIN32执行绪不是从创建处开始运行的,而是由 CreateThread指定一个函式,执行绪就从那个函式处开始运行。在WIN32中,全局变数是子执行绪与父执行绪共享的,这就是与Linux最大的不同之处。从上面的分析可以看出Windows的进程/执行绪要比Linux複杂。对于多任务系统,共享数据区是必要的,但也是一个容易引起混乱的问题,在WIN32下,执行绪之间的数据是共享的,一个执行绪修改过一个变数后,另一个执行绪却又修改了它,结果引起程式出问题。 但在Linux下,由于变数本来并不共享,而由程式设计师来显式地指定要共享的数据,使程式变得更清晰与安全。在进程管理及调度方面,Linux要比Windows的开销小。Linux是一个单块式的作业系统,作业系统通常在用户进程的记忆体空间内进行,可免去发生系统调用时的进程切换开销。Windows是一个準微核心作业系统,许多功能以单独的进程实现,从而提高了系统的模组化程度,但进程切换上的开销要大一些。
声明:此文信息来源于网络,登载此文只为提供信息参考,并不用于任何商业目的。如有侵权,请及时联系我们:baisebaisebaise@yeah.net
搜索
随机推荐

勇敢心资源网|豫ICP备19027550号