天天看点

进程 线程 管程进程管程线程死锁

进程

定义

程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。

在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行。这是这样的设计,大大提高了CPU的利用率。进程的出现让每个用户感觉到自己独享CPU,因此,进程就是为了在CPU上实现多道编程而提出的。

进程通信的分类

根据进程通信时信息量大小的不同,可以将进程通信划分为两大类型:控制信息的通信(低级通信)和大批数据信息的通信(高级通信).

低级通信主要用于进程之间的同步,互斥,终止和挂起等等控制信息的传递.

高级通信主要用于进程间数据块数据的交换和共享,常见的高级通信有管道,消息队列,共享内存等.

进程间的通信方式

#管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系一般指的是父子关系.管道一般用于两个不同进程之间的通信.当一个进程创建了一个管道,并调用fork创建自己的一个子进程后,父进程关闭读管道端,子进程关闭写管道端,这样提供了两个进程之间数据流动的一种方式.

#有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。

# 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

# 消息队列( message queue ) : 消息队列是消息的链表,存放在内核中并由消息队列标识符标识.消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等特点.消息队列是UNIX下不同进程之间可实现共享资源的一种机制,UNIX允许不同进程将格式化的数据流以消息队列形式发送给任意进程.对消息队列具有操作权限的进程都可以使用msget完成对消息队列的操作控制.通过使用消息类型,进程可以按任何顺序读信息,或为消息安排优先级顺序.

# 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

# 共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。

# 套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。

各种通信方式的优缺点

几种通信方法总结综上所述.进程之间的多种通信方法各自有各自的优点和缺点:如果用户传递的信息较少.或是需要通过信号来触发某些行为.前文提到的软中断信号机制不失为一种简捷有效的进程间通信方式.但若是进程间要求传递的信息量比较大或者进程间存在交换数据的要求,那就需要考虑别的通信方式了。无名管道简单方便.但局限于单向通信的工作方式.并且只能在创建它的进程及其子孙进程之间实现管道的共享:有名管道虽然可以提供给任意关系的进程使用.但是由于其长期存在于系统之中,使用不当容易出错.所以普通用户一般不建议使用。消息缓冲可以不再局限于父子进程.而允许任意进程通过共享消息队列来实现进程间通信.并由系统调用函数来实现消息发送和接收之间的同步.从而使得用户在使用消息缓冲进行通信时不再需要考虑同步问题.使用方便,但是消息队列中信息的复制需要额外消耗CPU的时间.不适宜于信息量大或操作频繁的场合。共享内存针对消息缓冲的缺点改而利用内存缓冲区直接交换信息,无须复制,快捷、信息量大是其优点。但是共享内存的通信方式是通过将共享的内存缓冲区直接附加到进程的虚拟地址空间中来实现的.因此,这些进程之间的读写操作的同步问题操作系统无法实现。必须由各进程利用其他同步工具解决。另外,由于内存实体存在于计算机系统中.所以只能由处于同一个计算机系统中的诸进程共享,不方便网络通信。不同的进程通信方式有不同的优点和缺点.因此.对于不同的应用问题,要根据问题本身的情况来选择进程间的通信方式。

一般来说,进程间的通信根据通信内容可以划分为两种:即控制信息的传送与大批数据传送。有时也把进程间控制信息的交换称为低级通信,而把进程间大批量数据的交换称为高级通信。

管程

信号量机制虽然是一种既方便又有效的进程同步机制,但是每个访问理解资源的进程都必须自备同步操作,不仅给系统管理带来麻烦,还很容易因同步操作不当造成系统死锁。这样一个新的进程同步工具就出现了——管程。

定义

代表系统共享资源的数据结构,以及有对该共享数据结构实施操作的一组过程所组成的资源管理程序,共同构成一个操作系统的资源管理模块,我们称之为“管程”。

管程被请求资源的进程所调用,有四部分组成:①管程的名称;②局部于管程内部的数据结构的说明;③对该数据结构进行操作的一组过程;④对局部于管程内部的共享数据设置初始值的语句;

管程相当于围墙,将共享数据结构全部圈了起来,只留下入口和出口,并且拥有自己的消息队列,每当进程要访问共享资源的时候,必须经过管程才能进入,而管程每次只准许一个进程进入管程,从而实现互斥。

管程的特性:

  1. 模块化。管程是一个基本程序单位,可以独立编译。
  2. 抽象数据类型。管程中不仅有数据,还有对数据的操作。
  3. 信息掩蔽。管程中的数据必须只能被管程来访问,这些过程也是在管程内部定义的,供管程外的进程调用,而管程中的数据结构以及具体实现外部都是不可见的。

管程与进程的区别:

1、二者虽然都定义的数据结构,但是进程的数据结构PCB是进程私有的,管程的数据结构是公共数据结构,如消息队列;

2、二者都存在对各自数据结构的操作,但进程是由顺序程序执行有关的操作,而管程主要是进行同步操作和资源初始化操作;

3、设置进程的目的就是实现系统的并发性,而管程是解决资源的同步使用问题;

4、进程通过调用管程中的过程来对共享数据结构进行操作,该过程就如同子程序一样被调用,因而进程的工作方式是主动的,而管程是被动的。

5、进程之间可以并发,但是管程是不能与其调用者并发的

6、进程具有动态性,而管程是操作系统中的一个资源管理模块,供进程调用。

线程

进程有很多优点,它提供了多道编程,让我们感觉我们每个人都拥有自己的CPU和其他资源,可以提高计算机的利用率。很多人就不理解了,既然进程这么优秀,为什么还要线程呢?其实,仔细观察就会发现进程还是有很多缺陷的,主要体现在两点上:

进程只能在一个时间干一件事,如果想同时干两件事或多件事,进程就无能为力了。

进程在执行的过程中如果阻塞,例如等待输入,整个进程就会挂起,即使进程中有些工作不依赖于输入的数据,也将无法执行。

如果这两个缺点理解比较困难的话,举个现实的例子也许你就清楚了:如果把我们上课的过程看成一个进程的话,那么我们要做的是耳朵听老师讲课,手上还要记笔记,脑子还要思考问题,这样才能高效的完成听课的任务。而如果只提供进程这个机制的话,上面这三件事将不能同时执行,同一时间只能做一件事,听的时候就不能记笔记,也不能用脑子思考,这是其一;如果老师在黑板上写演算过程,我们开始记笔记,而老师突然有一步推不下去了,阻塞住了,他在那边思考着,而我们呢,也不能干其他事,即使你想趁此时思考一下刚才没听懂的一个问题都不行,这是其二。

现在你应该明白了进程的缺陷了,而解决的办法很简单,我们完全可以让听、写、思三个独立的过程,并行起来,这样很明显可以提高听课的效率。而实际的操作系统中,也同样引入了这种类似的机制——线程。

线程的优点

因为要并发,我们发明了进程,又进一步发明了线程。只不过进程和线程的并发层次不同:进程属于在处理器这一层上提供的抽象;线程则属于在进程这个层次上再提供了一层并发的抽象。如果我们进入计算机体系结构里,就会发现,流水线提供的也是一种并发,不过是指令级的并发。这样,流水线、线程、进程就从低到高在三个层次上提供我们所迫切需要的并发!

除了提高进程的并发度,线程还有个好处,就是可以有效地利用多处理器和多核计算机。现在的处理器有个趋势就是朝着多核方向发展,在没有线程之前,多核并不能让一个进程的执行速度提高,原因还是上面所有的两点限制。但如果讲一个进程分解为若干个线程,则可以让不同的线程运行在不同的核上,从而提高了进程的执行速度。

例如:我们经常使用微软的Word进行文字排版,实际上就打开了多个线程。这些线程一个负责显示,一个接受键盘的输入,一个进行存盘等等。这些线程一起运行,让我们感觉到我们输入和屏幕显示同时发生,而不是输入一些字符,过一段时间才能看到显示出来。在我们不经意间,还进行了自动存盘操作。这就是线程给我们带来的方便之处。

进程与线程的区别

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。

线程是进程的一个实体, 是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。

一个程序至少有一个进程,一个进程至少有一个线程. 一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行,线程共享除了堆栈以外的进程资源。 与进程的控制表PCB相似,线程也有自己的控制表TCB,但是TCB中所保存的线程状态比PCB表少得多。

进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

死锁

产生原因

  • 资源竞争
  • 进程间推进

产生死锁的必要条件

  • 互斥
  • 请求和保持
  • 不剥夺
  • 环路等待

预防死锁

在产生死锁的必要条件上,加上摒弃(除了互斥条件,因为摒弃互斥,就不能保证并发的正确性了)

  • 摒弃请求和保持

    系统规定所有进程在开始执行之前,都要一次性的申请所需的全部资源。

  • 摒弃环路等待

    所有进程对资源的请求顺序必须按照资源号递增的顺序提出。

  • 摒弃不剥夺

    当一个进程已经拥有资源,并且又要请求新的资源的时候不能立即得到满足,必须立即释放它原有占有的资源,如果以后还需要此类资源,可以再重新申请。

避免死锁

银行家算法来进行死锁的避免。

检测死锁

保存有关资源的请求和分配信息

提供一种算法,以利用这些信息来检测系统是否已进入死锁状态

解除死锁

剥夺资源

撤销进程

继续阅读