Linux进程间的管道通信.doc_第1页
Linux进程间的管道通信.doc_第2页
Linux进程间的管道通信.doc_第3页
Linux进程间的管道通信.doc_第4页
Linux进程间的管道通信.doc_第5页
免费预览已结束,剩余6页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

河南师范大学本科毕业论文(设计)Linux进程间的管道通信摘 要:进程间通信可以通过传送文件来实现,不同的进程通过一个或多个文件来传递信息,事实上,在很多应用系统里,都使用了这种方法。但一般说来,进程间通信不包括这种似乎比较低级的通信方法。Unix系统中实现进程间通信的方法很多,极少方法能在所有的Unix系统中进行移植。而Linux作为一种新兴的操作系统,几乎支持所有的Unix下常用的进程间通信方法:管道、消息队列、共享内存、信号量等等。管道通信最能体现Linux平台的特色,所以本文以Linux平台下的管道通信为重点进行讨论。关键词:父进程; 子进程; 管道; 文件描述符Abstract: the pipeline communication among the progress can be realized through conveying the file. Different progress conveys information through a file or several files. In fact, in a lot of application systems, all used this kind of method. But generally speaking, progress communication include this kind seems low-grade communication method. Unix system realizes many methods of process commu- nication, few methods can transplant in all Unix systems. As a kind of new developing operating system, Linux nearly supports the communication method among the commonly used process under all Unix systems. For example, the pipeline, news formation, shared drive, the signal amount. Pipeline communication best embodies the characteristic of Linux platform, so this text takes pipeline communication under Linux platform as the focal point and discusses.Keywords: father progress; sub-progress; piping; the file describes incantations1引言在进程之间进行通信的最简单的方法是通过一个文件,其中有一个进程写文件,而另外一个进程从文件中读出,其优点体现在:(1) 只要进程对该文件具有访问权限,那么,两个进程间就可以通信;(2) 进程之间的数据可以非常大。尽管如此,使用文件进行进程间通信也有两大缺点:(1) 空间的浪费,写进程只有确保把数据加到文件的尾部才能使读进程读到数据, 对长时间存在的进程来说,这能使文件变的非常大;(2) 时间的浪费,如果读进程读数据的速度比写进程写数据快,那么,就可能出现读进程不断的读文件尾部,做很多无用功。要克服以上缺点而又使进程间相对简单,管道是一种较好的选择。管道是Linux中最常用的进程间的通信IPC机制,当输出的数据量特别大时,这种IPC机制非常有用,可以想象没有管道机制,利用文件传递,会造成很大的时间和空间的浪费。2管道的概念所谓管道,是指用于连接一个读进程和一个写进程,以实现它们之间通信的共享文件,又称pipe文件,向管道提供输入的发送进程,即写进程,以字符流形式将大量的数据送入管道;而接受管道输出的接受进程,即读进程,可从管道中接受数据。由于发送进程和接受进程是利用管道进行通信的,故又称管道通信1。通信进程在使用管理时应该注意三个方面的问题,(a) 互斥,当某个进程对管道进行读写操作时,其他的进程就不能使用它;(b) 感知对方的存在,只有感知对方存在才能发送出信息;(c) 同步,当发送进程把信息写满管道之后,自己便阻塞,等到接受进程取走信息后,唤醒它,当接受进程取到一个空管时,便阻塞自己,直到发送进程把信息写入管道,并把它唤醒为止1。管道通信机构必须提供以上三个方面的协调才能使通信正常进行。3管道机制的分析Linux外壳程序都允许重定位,例如 $ IS |pr |IPR 将列出目录文件命令IS的输出用管道送入IPR命令的标准输入,该命令在缺省的打印机上打印结果,管道是单方向的字节流,连接一个进程的标准输出到另一个进程的标准输入。这个例子并不复杂,只要对Unix比较熟悉的人都曾经使用过类似的命令。但是,在简单的命令下,Unix内核究竟都做了一些什么呢?当进程创建一个管道的时候,系统内核同时为该进程设立了一对文件句柄(一个流),一个用来从该管道获取数据(read),另一个则用做管道的输出(write)。图3.1显示了管道间的相互作用。系统内核句柄fd0句柄fd0句柄fd1句柄fd1进程 图3.1从图3.1中可以清楚的看出,进程和管道是如何通过句柄进行数据交换的。进程通过句柄FD0向管道写入数据,同时通过FD1从管道读出数据。联想到Unix的文件处理,事实上,在系统内核中,每个管道都是用一个Inode结点来表示的。当然,这个结点是看不到的,它只存在于系统内核中。系统内核句柄fd0句柄fd 0句柄fd1句柄fd1子 进 程父进程图3.2当然,一个管道只被用来同单个进程通信是没有意义的,建立一个同自己通信的管道是没有用处的。为了解决这个问题,在主进程打开的所有文件句柄。利用继承的句柄,就可以实现父子间的通信了。一个普通的管道仅可供具有共同祖先的两个进程之间共享,并且这个祖先必须已经建立了供它使用的管道。这个关系可以用图3.2来描述。 在Linux中,管道是用两个数据结构来实现的,这两个数据结构均指向同一临时VFS I-节点2,该节点指向内存中的一个物理面,如下图3显示,每个文件数据节点从普通文件读和向普通文件等系统调用的差别。当写的进程向管道中写时,字节被拷贝到共享数据页面。当读的进程从管道读时,字节从共享的数据页面拷贝出来,Linux同步到管道的访问,它必须保证管道的读和写的步调一致,为完成这一个任务,Linux使用了锁,等待队列和信号。 进程1 file结构 进程2file结构f-modef-posf-flagsf-countf-ownerf-inodef-opf-versionprivate-dataf-modef-posf-flagsf-countf-ownerf-inodef-opf-versionprivate-data inode 数据页 管道写操作 管道读操作图3.3当写进程想向管道写时,它使用标准的写库函数,这些函数均通过指向进程的文件数据结构集的文件描述符。每个表示一个打开的文件,或者在这种情况下,表示一个打开的管道。Linux系统调用使用由描述该管道的文件数据结构指向的写子程序。这个写子程序使用VFS I-节点中保存表示管道的信息来管理写请求。如果有足够的空间向管道中写所有的字节,只要管道来被读进程锁定,则Linux为写进程锁定管道,并从进程的地址空间将要写出的字节拷贝到共享数据页面。如果管道被读进程锁定或者没有足够的空间装数据,则当前进程进入睡眠状态,进入管道I-节点的等待队列,这时调度程序被调用,以便别的进程可以运行。进程是可中断的,它可以接受信号,当有足够的空间给写数据时,或管道解锁时,有读进程唤醒。当数据写完后,管道的VFS I-节点被解锁,任何在该节点上的等待队列中的等待的读进程将被自己唤醒。 从管道中读数据与向管道中写数据是非常相似的。进程被允许进行非块读(这取决于进程打开文件或管道的模式),在这种情况下,如果没有数据要读,或者管道被加锁,则令返回一个错误,直到写进程完成写操作,当两个进程完成了管道操作,则管道I-节点连同共享数据页面一起被放弃2。Linux 还支持命名管道,也叫做FIFO,因为管道是基于先进先出的原理进行的,先写进管道的数据先从管道中读出,与管道不同,FIFO不是临时对象,它们有访问FIFO的权限,FIFO打开的方式与管道有一点不同。管道是一次创建的,FIFO是已经存在的,有其使用者打开和关闭,Linux必须在写进程打开FIFO之前处理读进程打开FIFO,同时在写进程向FIFO写进程之前处理读进程的读操作,除此之外,处理FIFO的方式几乎与管道的处理方式完全一样,它们使用相同的数据结构和操作。4管道的建立和使用4.1管道的创建-pipe函数 函数原型:#include Int pipe(int pfd2); 调用成功时,返回值0;错误时,返回-1,并设置错误代码error。创建一个管道,pfd0和pfd1分别为管道两断的文件描述字,pfd0用于读,pfd1用于写。4.2写管道-write函数ret=write(pfd1,buf,n )若管道已满,则被阻塞,直到管道另一端read将已进入管道的数据取走为止。管道容量:假定一固定值,如8196字节4.3读管道-read函数ret=write(pfd0,buf,n)若管道已空,且写端文件描述字未关闭,则被阻塞。若管道写端已关闭,则返回0。若管道不为空,分两种情况:(设管道中实际有m个字节),如n=m,则读m个;如果n=m则读取n个。实际读取的数目作为read的返回值。注意:管道是无记录边界的字节流通信。4.4关闭管道-close函数关闭写端,导致读端read调用返回值为0。关闭读端,则导致写端write调用返回-1,error被设为EPIPE,在写端write函数退出前进程还会受到SIGPIPE信号(默认处理是终止进程,该信号可以被捕捉)。4.5文件描述的复制-dup2int dup2(int fd1,int fd2);复制文件描述符fd1到fd2,fd2可以是空闲的文件描述符,若关闭fd2,调用失败。5管道的操作3-5 管道的读端的操作和写端的操作的实现机制如下,5.1和5.2具体描述了写端和读端的的实现程序。5.1写端 #define syserr(str) perror(str);exit(1); main() int pfd2;char fdstr10,*message =”sendreceive data using pipe”; if(pipe(pfd)= =-1) syserr(“create pipe”); switch(fork) case -1; syserr(“fork”); case 0; /*child*/ close (pfd1); sprintf(fdstr ,”%d”,pfd0); execlp(“pread”,”pread”,fdstr,0); syserr(“execute pread file”); break; default:*parent* close(pfd0);if(write(pfd1,message,serlen(message0-1)= =-1) perror(“write pipe”); break; exit(0); 5.2读端#define syserr(str) perro9str;exit(1);4main(int argc,char * *argv) int fd,nbyte,I; char buf1024; fd =strtol(argv1,0,0); nbyte=read(fd,buf,sized(buf); switch(nbyte) case -1: syserr(ptpe closedn”); case 0: printf(“pipe closedn”); break; default: printf(“%d bytes%sn”,nbyte,buf); break; exit (0);6示例程序 ps ef ps.txt awk printf(“%s %sn”,$1,$2,$3); ps2.txt 程序的运行结果相当于运行了以上三条命令,即ps以长格式将当前所有用户进程输出重定向到ps.txt文件,awk文本处理命令从ps.txt输入重定向(只打印前3个参数)并作sort命令的管道输入,命令sort竟最终结果输出重定向到文件ps2.txt6。#include #include #include#includeint main() int fd1=-1,fd2=-1; fd1是ps.txt的描述符fd2是ps2.txt的描述符int fd2,sv; 定义管道pipe(fd); 建立管道进程一:ps ef输出重定向到ps.txtif (fork)()= = 0 fd 1=open(“ps.txt”,O_CREAT|O_WRONLY); dup2(fd1,1); close(fd1); execlp(“ps”,”ps”,”-ef”,0); else if(fork()= =0) 进程二:从管道重定向输出到ps2.txt dup2(fd0,0); close(fd0); fd2=open(“ps2.txt”,O_CREAT|O_WRONLY); dup2(fd2,1); close(fd2); execlp(“sort”,”sort”,0); else if(fork()= =0)进程三:awk 从ps.txt 重定向输入管道 dup2(fd1,1); close(fd0); close(fd1); fd1 = open(“ps.txt”,O_RDONLY); dup2(fd1,0); close(fd1); execlp(“awk”,”awk”,”printf(”%s %s n”,$1,$2,$3)”0); close(fd0);close(fd1); wait(& sv);wait($ sv);wait(&sv);7-87存在的几个问题7.1管道传输的是一个无记录边界的字节流写端一次write所发送数据,读端可能需要多次read才能读取。也有可能写端的多次write所发送的数据,读端read一次可以全部读出。7.2父进程需要双向通信时,应采用两个管道父子进程只使用一个管道双向数据传送时的问题,如果用一个管道,进程可能会收到自己刚写到管道去的原始数据,增加其他同步方式太复杂。7.3父子进程使用两个管道传递数据,有可能产生死锁父进程以输出管道满而写,导致被阻塞,子进程因要向父进程写回足够多的数据而导致写也被阻塞,这时死锁。7.4管道的缺点没有记录边界。多进程通信问题必须仔细分析流量控制和死锁问题9。8结束语随着Linux的快速发展,进程间的通信也被受欢迎,基于管道通信机制灵活,安全的模式必然越来越受到重视以及普遍应

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论