进程管理13.7进程通信(communication)进程通信:指进程间的信息交换。按通信内容可以划分为2种低级通信:进程之间控制信息的交换称为低级通信。一般只传送一个和几个字节的信息,达到控制进程执行速度的作用。(进程的同步和互斥)信号量机制作为同步工具是卓有成效的,但作为通讯工具则不够理想,(效率低。通讯对用户不透明。)高级通信:用户可以直接利用操作系统所提供的一组通信命令,高效地传送大量数据的一种通信方式。进程管理2进程的同步与互斥是一种通讯方式,一进程可通过修改变量或信号量告知另一进程,它是否可以继续执行下去,利用生产者——消费者算法,生产者进程可以传送一批数据给消费进程,或者说生产者通过缓冲区与消费者进行通讯,但P、V操作只能传递信号,信号本身不包含任何数据,而进程不当还容易导致进程死锁,因此,称这些同步机构为低级通讯机构.进程管理3进程通信的类型一、单机系统中进程间通信的四种形式主从式、会话式、消息或邮箱机制、共享存储区方式主从式通信系统的主要特点是:①主进程可自由地使用从进程的资源或数据;②从进程的动作受主进程的控制;③主进程和从进程的关系是固定的。1、主从式:例:终端控制进程和终端进程。进程管理4会话方式中,通信进程双方可分别称为使用进程和服务进程。其中,使用进程调用服务进程提供的服务。它们具有如下特点:①使用进程在使用服务进程所提供的服务之前,必须得到服务进程的许可;②服务进程根据使用进程的要求提供服务,但对所提供服务的控制由服务进程自身完成。③使用进程和服务进程在通信时有固定连接关系。2、会话方式进程管理5例如:用户进程与磁盘管理进程之间的通信是会话系统的一个例子。各用户进程向磁盘管理进程提出使用要求并得到许可之后,才可以使用相应的存储区。由磁盘管理进程自身完成对磁盘存储区的管理和控制。用户进程与磁盘管理进程之间,只有在用户进程要求使用磁盘存储区时才有通信关系。①使用进程在使用服务进程所提供的服务之前,必须得到服务进程的许可;②服务进程根据使用进程的要求提供服务,但对所提供服务的控制由服务进程自身完成。③使用进程和服务进程在通信时有固定连接关系。进程管理63、消息或邮箱机制消息或邮箱机制则无论接收进程是否已准备好接收消息,发送进程都将把所要发送的消息送入缓冲区或邮箱。消息的一般形式为4个部分组成。即:发送进程名、接收进程名、数据和有关数据的操作。消息或邮箱机制的特点是:①只要存在空缓冲区或邮箱,发送进程就可以发送消息。②发送进程和接收进程之间无直接连接关系。③发送进程和接收进程之间存在缓冲区或邮箱用来存放被传送消息。进程管理7消息的组成缓冲区或邮箱通信结构进程管理84、共享存储区共享存储区方式不要求数据移动。两个需要互相交换信息的进程通过对同一共享数据区的操作来达到互相通信的目的。这个共享数据区是每个互相通信进程的一个组成部分。进程管理9二、高级通讯机制类型1共享存储器系统2消息传递系统3管道(pipe)通信系统进程管理101共享存储器系统共享存储器系统:相互通讯的进程通过共享数据结构和存储区进行通讯,因而可进一步分为:基于共享数据结构的通讯方式;(低效,只适于传递少量数据)基于共享存储区的通讯方式。为了传送大量数据,在存储区中划出一块共享存储区,诸进程可通过对共享存储区进行读或写数据实现通讯。1向系统申请共享存储区中的一个分区2指定该分区的关键字3如果已经给其他进程分配了这样的存储区,将使用分区的描述符返回给申请者4申请者将申请到的共享分区挂到本进程上返回进程管理112消息传递系统在消息传递系统中,进程间的数据交换是以消息(message,在计算机网络中又称报文)为单位。程序员直接利用系统提供的一组通讯命令(原语)来实现通讯。直接通信方式(消息缓冲机制)间接通信方式(信箱通信方式)因其实现方法的不同,又可分为:消息的一般形式:发送消息的进程名、接收消息的进程名、消息长度、消息正文等。进程管理12直接通信方式:发送进程直接将消息发送给接收进程,并将它挂在接收进程的消息缓冲队列上。接收进程从消息缓冲队列中取得消息。故称为消息缓冲机制。间接通信方式:发送进程将消息发送到某个中间实体(一般称为信箱)中,接收进程从中取得消息,所以称为信箱通讯方式,相应地系统称为电子邮件系统。进程管理13消息缓冲机制(直接通信)发送进程在自己的内存空间生成消息申请、并发送消息至缓冲区消息队列1接收进程在自己的内存空间设置一个公用缓冲区两通信进程必须满足下列条件:1、在发送进程把消息写入缓冲区和把缓冲区挂入消息队列时,应禁止其他进程对缓冲区消息队列的访问。同理,接收进程取消息时也禁止其他进程访问缓冲区消息队列2、当缓冲区中没有信息存在时,接收进程不能接收到任何消息消息队列2接受区发送进程和接收进程发送原语Send()和接收原语receive()设公用信号量mutex,并置初值为1设SM为接收进程的私用信号量,置初值为0Send(m)begin向系统申请一个消息缓冲区P(mutex)使用公用缓冲区将发送区消息m送入新申请的消息缓冲区把消息缓冲区挂入接收进程的消息队列V(mutex)释放缓冲区V(SM)向接收进程发送消息endReceive(m)beginP(SM)等待接的消息的个数P(mutex)使用公用缓冲区摘下消息队列中的消息m将消息队列m从缓冲区复制到接收区释放缓冲区V(mutex)释放公用缓冲区end进程管理15邮箱通信(间接通信)1.信(邮)箱信箱是一种数据结构,逻辑上它分成两部分:信箱头和由若干格子组成的信箱体。信箱中每个格子存放一封信,信箱中格子的数目和每格的大小在创建信箱时确定。进程间的通信要满足如下条件:a.发送进程发送消息时,邮箱中至少要有一个空格存放该消息。b.接收进程接收消息时,邮箱中至少要有一个消息存在。进程管理16信箱可由OS创建,也可由用户进程创建,创建者是信箱的拥有者,据此可把信箱分为:私用信箱,公用信箱,共享信箱。进程管理17发送进程A邮箱头…邮箱体接收进程BDeposite(m)Remove(m)邮箱通信结构邮箱头:邮箱名称、邮箱大小、拥有该邮箱的进程名邮箱体:存放消息使用邮箱的时候应该满足:1发送进程发送消息时,邮箱中至少要有一个空格能存放该消息2接收进程接收消息时,邮箱中至少有一个消息存在进程管理18发送进程调用过程deposit(m)将消息发送到邮箱,接收进程调用过程remove(m),将消息m从邮箱中取出。Fromnum—发送进程的私用信号量。记录信箱空格,初值为nMesnum—接收进程的私用信号量。记录信箱有消息的个数初值为0进程管理19Fromnum记录信箱空格,初值为nMesnum记录信箱有消息的个数初值为0Deposit(m);BeginlocalxP(fromnum)空格数减1选择空格x将消息m放入空格x中置格x的标志为满V(mesnum)向接收进程发送消息end消息个数+1Remove(m)beinglocalxP(mesnum)消息个数加1选择满格x把满格x中的消息取出放m中置格x标志为空V(mesnum)空格个数加1end返回进程管理203.7.5进程通信实例――管道管道(pipe)通讯由UNIX首创的一种借助文件和文件系统形成的一种通信方式.由于其有效性,一些系统继UNIX之后相继引入了管道技术,如pc-dos,管道通信将成为进程通讯的一种重要方式。消息缓冲通信机构是以内存缓冲区为基础。管道是以文件系统为基础。管道类别:有名管道(mknod建立)、无名管道(pipe)进程管理21管道:是指用于连接一个读进程和一个写进程,以实现它们之间通信的共享方式,又称pipe文件。管道(共享文件)提供输入的发送进程(即写进程),以字符流形式将大量的数据送入管道;而接收管道输出的接收进程(即读进程),可从管道接收数据,由于发送和接收都是利用管道进行通信的,故称为管道通信。进程管理22为了协调双方的通信,管道通信机制必须提供以下三方面的协调能力:互斥:一个进程正在对pipe进行读/写操作时,另一进程必须等待。同步:当写(输入)进程把一定数量的数据写入pipe后,便去睡眠等待,直到读(输出)进程取走数据将其唤醒;当读进程读一空pipe,也应睡眠等待,直至写进程将数据写入管道,才将其唤醒。对方是否存在:只有确定对方已存在时,才能进行管道通信,否则会造成因对方不存在而无限期等待。进程管理231.Pipe的建立和使用方式pipe文件在使用之前,必须先由使用者建立并打开:pipe(fd);//定义管道intfd[2];//定义两端fd[0]:读出端;fd[1]:写入端进程管理24系统文件write(fd[1],buf,size)功能:把buf中的长度为size字符的消息送入管道入口fd[1]。fd[1]—pipe入口buf:存放消息的空间size:要写入的字符长度系统文件read(fd[0],buf,size)fd[0]――Pipe的出口功能:从pipe出口fd[0]读出size字符的消息置入buf中。进程管理25pipe只允许建立者及其子进程使用。一进程及其所有‘子孙’构成一个进程族,同族中的多个进程可共享一个pipe,为了避免混乱,通常一个pipe为两个进程专用,且一个进程只用其写入端,另一进程只用其读出端。pipe(fd)写入端读出端fd[1]write(fd[1],buf,size)fd[0]read(fd[0],buf,size)管道按先进现出方式FIFO传送消息,且只能单向传送消息进程管理261.pipe文件的读写操作的同步与互斥如同消息缓冲一样,在对pipe文件进行读写操作过程中要对发送进程和接送进程实施正确的同步与互斥以确保通信的正确性.接收进程:当接收进程读pipe时,若发现pipe为空,则进入等待状态。一旦有发送进程对该pipe执行写操作是唤醒等待进程.进程管理27发送进程:当发送进程在写pipe时,总是先按pipe文件的当前长度设置,如果pipe文件长度已经到4096字节,但仍有一部分信息没有写入,则系统使要求写pipe的进程进入睡眠状态,当读pipe进程收走了全部信息时,此时,系统再唤醒待写的进程。它将余下部分信息继续送入pipe中。进程管理28例1:建立一个pipe,同时父进程生成一个子进程,子进程向pipe中写入一字符串,父进程从pipe中读出该字符串。程序如下:#include〈stdio.h〉main(){intx,fd[2];charbuf[30],s[30];pipe(fd);/*创建管道*/while((x=fork())==-1);if(x==0)进程管理29{sprintf(buf,″Thisisanexample\n″);write(fd[1],buf,30);/*buf中字符写入管道*exit(0);}else/*父进程返回*/{wait(0);read(fd[0],s,30);/*父进程读管道中字符*/printf(″%s″,s);}}进程管理30例2:编写一程序,建立一个管道。同时,父进程生成子进程P1,P2,这两个子进程分别向管道中写入各自的字符串,父进程读出它们(如图)。图父进程和子进程P1,P2通信例子进程管理31解:程序框图如图3.22所示,源程序如下:进程管理32#include〈stdio.h〉main(){inti,r,p1,p2,fd[2];charbuf[50],s[50];pipe(fd);/*父进程建立管道*/while((p1=fork())==-1);/*创建子进程P1,失败时循环*/if(p1==0)/*由子进程P1返回,执行子进程P1*/{lockf(fd[1],1,0);/*加锁锁定写入端*/sprintf(buf,″childprocessP1issendingmessages!\n″);printf(″childprocessP1!\n″);write(fd[1],buf,50);/*把buf中的50个字符写入管道*/sleep(5);/*睡眠5秒,让父进程读*/lockf(fd[