Chinaunix首页 | 论坛 | 博客
  • 博客访问: 19733857
  • 博文数量: 679
  • 博客积分: 10495
  • 博客等级: 上将
  • 技术积分: 9308
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-18 10:51
文章分类

全部博文(679)

文章存档

2012年(5)

2011年(38)

2010年(86)

2009年(145)

2008年(170)

2007年(165)

2006年(89)

分类: LINUX

2007-12-20 10:00:02

处理机管理

提高处理机使用率的技术措施主要是多道和分时

本章主要围绕处理机管理展开,着重介绍进程的概念,同时也包括相关的两个基本概念:作业和线程。

§2.1  作业

 

作业是用户向计算机系统提交一项工作的基本单位,是用户在一次事务处理或计算过程中要求计算机所做工作的总和。

作业和程序是两个相互联系而又不同的概念。如果一次业务处理可以由某一个程序完成,就是说这个业务处理只要提交这一个程序就够了,这种情况下,这个程序就是一个作业。通常,完成一次业务需要由多个程序协同完成,这时,多个程序、这些程序需要的数据以及必要的作业说明一起构成一个作业。系统通过作业说明书或者作业控制语句(JCL)控制程序和相应的数据执行,完成整个业务处理。

按照对作业的处理方式,可以分为联机、批处理等作业。

Linux系统中的shell提供了操作系统和用户之间的联机命令接口。

Linuxshell同时提供了程序级接口。用户通过提交一个命令或一个命令序列以批处理方式执行特定的操作(详见本书第2部分)。

Linux分时批处理系统中,也可以根据对作业执行时的响应特征分为前台作业和后台作业。

在多用户系统中,多个用户、不同类型的作业可能同时请求执行,控制和管理这些作业,协调它们之间的关系,就是作业调度,作业调度是处理机调度的一部分。

 

 

§2.2  进程

本节着重讨论现代多道操作系统中的核心概念——进程,这是理解操作系统工作原理的基础和关键。首先介绍单个进程的状态、状态转换的条件和控制原语、进程在系统中的静态描述等,接着介绍多个进程之间的约束关系,由此引出进程间通信的概念,通信是协调、解决进程间约束关系的惟一手段,这种约束关系处理不当造成的最严重的后果就是死锁

 

     进程的概念

进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动.

进程的独立性:进程是操作系统分配资源和进行调度的独立单位。

进程的动态性:程序的一次运行活动,强调动态执行。

进程的并发性:对于单处理机系统,进程宏观上同时运行而微观上是依次执行,这种情况称为并发执行。

 

-*进程和程序

程序是指令的有序集合,是一个静态的概念,描述完成某个功能的一个具体操作过程,而进程是程序针对某一组数据的一次执行过程,更强调动态特征。一个完整的进程,包括程序、执行程序所需要的数据,同时还必须包括记录进程状态的数据资料。

一个程序在处理相同或不同的操作数据时可以同时对应于多个进程。一个进程也可以包含多个程序.

 

 

-*进程和作业的区别。

作业是用户向计算机系统提交一项工作的基本单位,是用户在一次事务处理或计算过程中要求计算机所做工作的总和。进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,是操作系统分配资源和进行调度的基本单位。

作业是描述用户向系统提交工作任务的实体单位,而进程是系统完成工作任务时程序执行的实体单位。

对于批处理系统,通常,作业放在外存中专门的作业队列中等待进入内存执行,要经过一次宏观调度,由外存进入内存,以进程的形式运行。而对于UNIX/Linux这样的分时系统,没有宏观调度,作业不经过调度,直接进入内存,以进程的形式开始运行。任何一个进程,都存在于内存中,并且是已经开始运行的动态实体。

 

     进程描述

-*进程控制块

 

进程控制块是进程在内存中的静态存在方式。进程切换现场称为进程上下文(context),包含了一个进程所具有的全部信息,一般包括:进程控制块(Process Control BlockPCB)、有关程序段和相应的数据集,具体组成见图2.1PCB是记录进程各种状态的数据体,PCB是操作系统管理感知、控制进程的数据实体,通过它,就可以找到进程的程序段和数据集,系统正是通过PCB来控制进程的。

2.1 进程描述数据关系示意图(进程上下文)

PCB一般可以分为进程描述信息、进程控制信息,进程相关的资源信息和CPU现场保护机构。

 

-*Linux PCB

       Linux系统的进程控制块PCB用一个称为task-struct的结构体来描述。定义在源代码 include/linux/sched.c。包含

       ――*进程描述信息。 进程号(pidprocess identifier),用户和组标识(user and group identifier,连接信息(Links)。

       Linux使用组将文件和目录的访问特权授予一组用户,一个进程可以同时属于多个组(最多为32个),这些组都被放在进程的task-struct中的group数组中。

       Linux系统中的进程之间形成树状的家族关系,连接信息记录某个进程的父进程、兄弟进程(具有相同父进程的进程)以及子进程的信息,描述一个进程在整个家族系统中的具体位置。

      

       ――*进程控制信息: 进程当前状态、调度信息、计时信息、通信信息。

记时信息 包括时间和定时器,给出进程占有和利用CPU的情况,是调度的依据,也是进行统计、分析以及记费的依据。

Linux支持典型的UNIX进程间通信机制——信号、管道,也支持System Ⅴ通信机制——共享内存、信号量和消息队列。

 

       ――*进程资源信息:

       LinuxPCB中包含大量的系统资源信息,这些信息记录了与该进程有关的存储器的各种地址和资料、文件系统以及打开文件的信息等等。通过这些资料,进程就可以得到运行需要的相关程序段以及必要的数据。

――*CPU现场信息:

进程的静态描述必须保证一个进程在获得处理机并重新进入运行状态时,能够精确地接着上次运行的位置继续进行。相关程序段和数据集以及处理机现场(或处理机状态)都必须保存。处理机(CPU)现场信息一般包括处理机的内部寄存器和堆栈等基本数据。

 

task-structLinux系统的进程控制块(PCB),通过对PCB的操作,系统为进程分配资源并进行调度,最终完成进程的创建和撤销。系统利用PCB中的描述信息来标识一个进程,根据PCB中的调度信息决定该进程是否应该运行。如果这个进程要进入运行,首先根据其中的CPU现场信息来恢复运行现场,然后根据资源信息获取对应的程序段和数据集,接着上次的位置开始执行,同时通过PCB中的通信信息和其他进程协同工作。

     进程的状态及转换

       进程的基本状态:执行,就绪,等待

2.2 进程基本状态及转换示意图

 

       Linux 系统(2.2.*-2.4.*)进程状态如下:

TASK_RUNNING       0     运行态

TASK_INTERRUPTIBLE         1     等待态,可中断

TASK_UNINTERRUPTIBLE    2     等待态,不可中断

TASK_ZOMBIE   4     僵死态

TASK_STOPPED             8     暂停态

TASK_SWAPPING            16   交换态(2.4.*取消)

TASK_EXCLUSIVE    32   独占态

 

运行态包含了执行和就绪,靠是否占CPU来区分。每个CPU都有一个current指针。

等待状态:Linux系统把基本的等待状态进一步细化为可中断的等待态和不可中断的等待态两种。处于这种状态的进程都在等待某个事件或某个资源,可中断等待状态的进程可以被信号唤醒而进入就绪状态等待调度,而不可中断等待状态的进程是因为硬件资源无法满足,不能被信号唤醒,必须等到所等待的资源得到之后由特定的方式唤醒。

僵死:由于某些原因进程被终止,这个进程所拥有的内存、文件等资源全部释放之后,还保存着PCB信息,这种占有PCB但已经无法运行的进程就处于僵死状态。

暂停:处于暂停状态的进程,一般都是由运行状态转换而来,等待某种特殊处理。比如处于调试跟踪的程序,每执行到一个断点,就转入暂停状态,等待新的输入信号。

独占状态是等待状态的一种,优先唤醒,避免其他唤醒多个的选择。

       交换状态 :处于交换状态的进程正在执行内存、外存的交换工作。这个状态在2.2.X版本的内核中基本已经不使用,在2.4.X版本中没有这种状态。

      

一个处于执行状态的进程调用退出函数exit之后,进程就会进入僵死状态,这种状态下,进程释放了PCB之外的所有系统资源。也就是说,它在系统中只留下这个进程的一个PCB

僵死进程的父进程通过PCB了解到该进程所处的状态后,采取相应的处理措施,回收PCB,这个进程就完成了它的使命,从僵死走向彻底消亡,上图右上方的虚箭头表示了这种结局

 

     进程控制

进程控制,是指对系统中的全部进程实施有效的管理,使得进程能够及时创建、撤销,正确地完成进程各状态之间的转换,使得多个进程高效率并发执行,达到系统资源高度共享的目的。

       三种控制方式:进程控制原语、系统核心函数(比如调度)、外部事件发生(比如中断)。这里主要介绍原语。

 

       原语:系统状态下执行的一些具有特定功能的程序段,这些程序段具有原子性。有创建、撤销、阻塞、唤醒原语。

 

进程创建原语用于建立一个新的进程,这个新进程可以由内核调用进程创建原语建立,也可以由父进程执行进程创建原语生成一个子进程,子进程还可以生成子进程,以形成树形进程家族结构。进程创建原语的主要任务是形成进程的PCB 因此,调用者必须提供有关的参数,例如进程名、进程优先级、进程正文段起始地址、资源清单等

 

当正在运行的进程需要等待某一事件,由自己调用阻塞原语把自己阻塞起来成为等待状态。阻塞原语主要完成保护CPU现场的工作, 即首先中断处理机保存该进程的CPU现场,然后把被阻塞的进程置为等待状态,插入到相应的等待队列,最后转入进程调度程序,从就绪队列中选择一个进程投入运行。

当处于等待状态的进程所等待的事件出现时,由发现者进程调用唤醒原语唤醒被阻塞的进程。

 

进程控制原语由系统执行。同时,操作系统还提供了一些用于进程控制的系统调用和操作命令,用户可以通过程序或者命令的方式控制进程。

 

     进程约束

       进程之间有竞争和合作的关系。比如生产者-消费者(producercomsumer problem),也称为有界缓冲区问题(bounded buffer problem.临界资源(critical section

进程通信

在并发系统中,进程之间相互制约,具有同步和互斥是相当普遍的现象。这种进程之间的相互关系,依靠单个进程自身的力量是无法解决的,必须以进程间的相互通信为基础,互相发送信息,才能协调解决。具体的同步、互斥实现方案有很多种,分别基于不同的通信方式。

 

     进程通信

进程间通信是协调解决多个进程之间的约束关系,实现进程共同进展的关键技术,是多道系统中控制进程并发执行必不可少的机制。进程间的通信有两种方式:一是互相发送少量的控制信息,一般只传递一个或者几个字节的数据,进程利用这些简单的信息,实现互斥和同步,控制运行速度,这种简单的通信方式被称为进程间的低级通信;另外一种方式称为进程间的高级通信,基本不涉及进程执行速度控制,用来在进程之间传递大量的信息,由于这种通信方式主要用于交换信息, 因此,在开发本地进程间通信的同时,也为远程进程间的通信,和计算机网络的开发及控制奠定了基础。     进程通信类型:按通信进程双方的地位,可以分为:主从式、会话式、消息或邮箱机制以及共享存储区四种类型。

按照通信进程双方的地位,可以把进程通信分为:主从式、会话式、消息或邮箱机制以及共享存储区四种类型。

Linux系统提供了多种通信机制。包含传统UNIX通信机制信号和管道,UNIX system V IPC的通信机制信号量、消息队列和共享内存和套接字利用这些机制,可以方便地进行进程之间的相互协调,实现进程的互斥和同步。

 

-*信号

信号属于Linux系统的低级通信,主要用于在进程之间传递控制信号,实现进程的互斥和同步

信号可以发给一个或多个进程,可以是由某个进程发出,也可以由键盘中断产生,还可以是由shell程序向其子进程发送任务控制命令时产生。进程在某些系统错误环境下也会有信号产生。

除了两个信号外,进程可以忽略这些信号中的绝大部分,这两个信号是引起进程终止执行的SIGSTOP信号和引起进程退出的SIGKILL信号。至于其他信号,进程可以选择处理它们的具体方式。信号没有固有的相对优先级。

并不是系统中每个进程都可以向所有其他进程发送信号,只有核心和超级用户具有此权限。普通进程只能向具有相同uidgid的进程或者在同一进程组中的进程发送信号。信号是通过设置task-struct结构中signal域里的某一位来产生的。如果进程没有阻塞信号并且处于可中断的等待状态,则可以将其状态改成running,若确认进程还处在运行队列中,就可以通过信号唤醒它。

 

-*管道

管道是UNIX操作系统传统的进程通信技术。Linux管道通信包括无名管道和有名管道两种,通过文件系统来实现。管道也是一种特殊的文件类型,实际上是通过文件系统的高速缓冲实现的。

两个进程通过管道进行通信时,两个进程分别进行读和写操作,都指向缓冲区中同样的物理单元,一个进程写入数据,另一个进程从缓冲区中读取数据,从而实现信息传递。管道方式只能按照先进先出方式单向传递信息。管道方式可以用来进行大规模的数据传递

 

-*SYSTEM V 进程间通信:

信号量、消息队列和共享内存是UNIX/Linux系统常用的通信方式。

消息队列用来在进程之间传递分类的格式化数据,共享内存方式可以使不同进程共同访问一块虚拟存储空间,通过对该存储区的共同操作来实现数据传递,信号量主要用于进程之间的同步控制,通常和共享内存共同使用。

这三种方式在系统中是作为一个整体实现的。

共享内存是这三种方式中通信效率最高的,它在进程的虚拟空间中进行,而且不需要数据的移动也可以实现大规模的数据传递。    

套接字

 

-*套接字

套接字是用来通过网络实现运行于不同计算机上的进程之间通信的机制。它可以实现数据的双向规模传递,是整个网络通信的基础。具体的原理和实现与网络协议等有关,不做具体的介绍。

 

 

     死锁

死锁出现的根本原因是系统资源的有限性。并发进程竞争资源,调度不当,就可能出现死锁的情况,因此必须采取适当的措施来消除死锁。

产生死锁的必要条件有四个:并发进程之间是互斥关系,每个进程必须独占某个系统资源;进程占有的资源在未结束使用之前,不能被强行剥夺,只能由该进程自己释放;进程需要的资源采用部分分配的方式,在等待新资源的同时,继续占有已分配的资源;各占有资源的进程形成环路,每一个进程已获得的资源同时被下一个进程请求。

解决死锁的方案就是破坏死锁产生的必要条件。方法分为预防、回避、检测恢复三种。预防指采取某种策略,控制并发进程对资源的请求,保证死锁的四个必要条件在系统运行的任何时刻都无法满足。避免指系统采取某种算法,对资源使用情况进行预测,使资源分配尽可能合理,避免死锁的发生。这两种方法需要大量的系统开销,而且系统的资源也无法得到充分的利用。因此,一般系统都采取检测恢复的方法,这种方法是在死锁发生之后,根据系统情况,检测死锁发生的位置和原因,使用外力,重新分配资源,破坏死锁发生的条件,系统就可以从死锁状态恢复正常运行,这样的方法只要使用少量的系统资源,尤其是CPU时间就可以排除死锁

 

§2.3  线程

     线程的概念

 

       进程切换的时间和资源耗费较大,尤其是需要频繁切换的任务,为此引入线程。线程是进程内的基本调度单位。可以看做执行流,拥有记录自己状态和运行现场的少量数据(栈段和上下文),没有单独的代码段和数据段,而是和其他线程共享。一个进程可以看成一个虚拟处理器。线程又被称作轻权进程(light weight process)。有用户级和系统级线程。后者由内核完成,但是效率低一些。

       线程的记录信息包含线程控制块(Thread Control Block, TCB,堆栈和寄存器信息。

      

       进程的调度主要由操作系统完成,线程可由系统和用户。

 

       Linux可以同时支持内核级线程(kernel level threads),和用户级线程(user level threads

       用户级线程指不需要内核支持,在用户程序中实现的线程都需要用户程序自己完成。系统级线程由内核完成线程的调度并提供相应的系统调用,用户程序可以通过这些接口函数对线程进行一定的控制和管理。

用户级线程不需要额外的内核开销,一般只要提供一个线程库即可,剩下的工作就主要由用户自己负责了。但是由于用户级线程与系统内核无关,当一个进程因I/O而被调度程序切换为等待状态时,属于该进程的某个执行线程可能仍然处于执行状态。

       系统级线程的调度由内核完成,不需要更多用户干预,但要占用更多的系统开销,效率相对低一些。、

 

     线程和进程

 

进程是操作系统资源分配和系统调度的基本单位,每一个进程都有自己独立的地址空间和各种资源,线程也是一种系统调度的基本单位,多个线程可以共享一个进程的资源,在存储方面,线程占用的资源更少。

进程的调度主要由操作系统完成,而线程根据其类型的不同,可以由系统调度(内核级线程),也可以由用户进行调度(用户级线程)。

进程调度的过程中要进行切换,切换现场的保护与恢复要求对进程上下文做完整的记录,要消耗一定的存储资源和处理机时间;线程共享进程的资源,可以在进程内部切换,不涉及资源保存和内存地址变换等操作,可以节约大量的空间和时间资源。因此,对于切换频繁的工作任务,多线程方式比多进程方式可以提供更高的响应速度。

多个线程共享同一进程的资源,线程相互间通讯容易。而进程间通讯一般必须要通过系统提供的进程间通讯机制。

进程和线程都是用来描述程序的运行活动,是存在于系统存储区中的动态实体,都有自己的状态,整个生命周期都在不同的状态之间切换。

 

     Linux系统的线程

Linux可以同时支持内核级线程(也称为系统级线程)和用户级线程。

Linux的系统级线程在表示格式、管理调度等方面与进程没有严格的区分,都是当作进程来统一对待。

Linux系统级线程和进程的区别主要在于资源管理方面,线程可以共享父进程的部分资源(执行上下文)。在Linux系统中,线程共享资源的类型是可以控制的,系统调用clone里有五种形式的cloneCLONE-VM(存储空间),CLONE-FILES(文件描述表),CLONE-FD(文件系统信息),CLONE-SIGHAND(信号控制表),CLONE-PID(进程号)。

Linux的内核级线程和其他操作系统的内核实现不同。大多数操作系统单独定义描述线程的数据结构,采用独立的线程管理方式,提供专门的线程调度,这些都增加了内核和调度程序的复杂性。而在Linux中,将线程定义为“执行上下文”,它实际只是进程的另外一个执行上下文而已,和进程采用同样的表示、管理、调度方式。这样,Linux内核并不需要区分进程和线程,只需要一个进程/线程数组,而且调度程序也只有进程的调度程序,内核的实现相对简单得多,而且节约系统的用于管理方面的时间开销。但是,Linux系统使用相对复杂的进程控制块来记录信息,而线程本身的控制信息很少,完全可以采用相当简单的线程控制块数据结构,这就造成了内存空间的一定浪费。

一个值得注意的问题是,在Linux系统中,专门有一种称为kernel threads的线程,直译为内核线程,它和我们这里讨论的系统级线程(kernel level threads)在Linux系统中是两个完全不同的概念,它们的区别,将在4.3节“Linux进程调度”中详细介绍。

Linux支持POSIX标准定义的线程(pthreads),提供用户级线程支持。利用这样的线程库函数,用户可以方便地创建、调度和撤销线程,也可以实现线程间通信,而且这些线程还可以映射为系统级线程,由系统调度执行。实现用户级线程创建的函数是pthread-create

 

2.4   小结

进程是现代操作系统的核心概念,它用来描述程序执行的过程,是实现多道操作系统的基础。和进程联系密切的概念是程序、作业和线程,正确地区分和理解这些概念,有助于正确地理解和认识计算机操作系统本身。

Linux系统中基本没有区分进程和线程,它们都使用相同的描述方法,使用相同的调度和管理策略。描述进程的静态数据是进程控制块PCB。在Linux等多道操作系统中,程序是并发执行的,进程的个数总是多于系统CPU的个数,宏观上所有进程同时都在运行,微观上这些进程轮流使用CPU,在执行、等待和就绪等基本状态之间转换,直到执行完成。

 

习题

2-1 什么是作业?简述Linux系统作业的概念。

2-2 作业、程序和进程有什么区别?

2-3 进程能不能理解为由伪处理机执行的一个程序?为什么?

2-4 什么是进程间的互斥和同步?

2-5 并发进程间的制约有哪几种?引起的原因分别是什么?

2-6 Linux系统中的线程有哪几类?分别是如何描述和管理的?

2-7 访问Internet,了解Linux系统进程控制块的现状,有哪些改进,你认为改进方案如何?

阅读(4338) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~