进程间通信——管道

Posted on 2009-07-18 13:51 天边蓝 阅读(1961) 评论(0)  编辑 收藏 引用 所属分类: Linux

管道简介
常说的管道都是匿名半双工管道,匿名半双工管道在系统中是没有实名的,并不可以在文件系统中以任何方式看到该管道。它只是进程的一种资源,会随着进程的结束而被系统清除。管道通信是在UNIX系统中应用比较频繁的一种方式,例如使用grep查找:ls |grep ipc
顾名思义,匿名半双工管道没有名字,这个特性导致了它在应用方面的局限性:
       1.只能在有具有公共祖先的进程间通信,即或是父子关系进程间、或是在兄弟关系进程间通信。
       2.数据只能在一个方向上移动
管道创建
尽管这样,半双工管道还是Linux系统上最常见的通信方式。Linux系统用pipe函数创建一个半双工管道,期函数原型为:
        include<unistd.h>
        int pipe(int fd[2]);
     参数fd是一个长度为2的文件描述符,fd[1]为输入文件描述符,fd[1]为输出文件描述符;函数返回类型为int,0表示成功,-1表示失败。当成功返回时,则自动维护一个从fd[1]到fd[0]的同行管道。
管道操作
对管道进行读写,可以通过write和read进行:
            write(fd[1], "create the pipe successfully !\n", 31 ); /*向管道写入端写入数据*/
                     char str[256];
                     read(fd[0], str, sizeof(str) ); /*从管道读出端读出数据*/
       读写时,需要注意的问题:
                     1.当输出端关闭时,对输入端的写操作会产生信号SIGPIPE,说明管道读端已经关闭,并且write操作返回为–1,errno的值为EPIPE,对于SIGPIPE信号可以进行捕捉处理。
            2.read返回0说明管道中没数据,但不能说明输入端是否关闭
操作流程
    1.创建管道
    2.利用fork创建子进程
    3.控制管道流向
    4.从fd[1]向管道写信息
    5.通过fd[0]从管道渡信息
创建管道的标准库函数
     #include <stdio.h>
         FILE *popen( const char * command, const char *mode );
         int pclose ( FILE *stream ); 
示例
引用《Linux C程序设计大全》 中的例子
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#define BUFES PIPE_BUF /* PIPE_BUF管道默认一次性读写的数据长度*/
int main ( void ) {
         int fd[2];
         char buf[BUFSZ];
         pid_t pid;
         int len;
         if ( (pipe(fd)) < 0 ){ /*创建管道*/
                  perror ( "failed to pipe" );
                  exit( 1 );
         }
         if ( (pid = fork()) < 0 ){ /* 创建一个子进程 */
                  perror ( "failed to fork " );
                  exit( 1 );
         }
         else if ( pid > 0 ){
                close ( fd[0] ); /*父进程中关闭管道的读出端*/
                 write (fd[1], "hello my son!\n", 14 ); /*父进程向管道写入数据*/
                 exit ( 0);
         }
         else {
                 close ( fd[1] ); /*子进程关闭管道的写入端*/
                len = read (fd[0], buf, BUFS ); /*子进程从管道中读出数据*/
        if ( len < 0 ){
                 perror ( "process failed when read a pipe " );
                 exit( 1 );
        }
         else
                 write(STDOUT_FILENO, buf, len); /*输出到标准输出*/
                 exit(0);
         }
}


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


Copyright © 天边蓝