Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1729303
  • 博文数量: 347
  • 博客积分: 9328
  • 博客等级: 中将
  • 技术积分: 2680
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-29 23:45
文章分类

全部博文(347)

文章存档

2016年(1)

2013年(4)

2012年(207)

2011年(85)

2010年(50)

分类: LINUX

2012-11-19 09:42:05

进程间通信——管道
管道简介
常说的管道都是匿名半双工管道,匿名半双工管道在系统中是没有实名的,并不可以在文件系统中以任何方式看到该管道。它只是进程的一种资源,会随着进程的结束而被系统清除。管道通信是在UNIX系统中应用比较频繁的一种方式,例如使用grep查找:ls |grep ipc
顾名思义,匿名半双工管道没有名字,这个特性导致了它在应用方面的局限性:
       1.只能在有具有公共祖先的进程间通信,即或是父子关系进程间、或是在兄弟关系进程间通信。
       2.数据只能在一个方向上移动
管道创建
尽管这样,半双工管道还是Linux系统上最常见的通信方式。Linux系统用pipe函数创建一个半双工管道,期函数原型为:
        include
        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
         FILE *popen( const char * command, const char *mode ); 
         int pclose ( FILE *stream );  
示例
引用《Linux C程序设计大全》 中的例子

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. #include <fcntl.h>
  4. #include <sys/types.h>
  5. #define BUFES PIPE_BUF /* PIPE_BUF管道默认一次性读写的数据长度*/
  6. int main ( void ) {
  7.          int fd[2];
  8.          char buf[BUFSZ];
  9.          pid_t pid;
  10.          int len;
  11.          if ( (pipe(fd)) < 0 ){ /*创建管道*/
  12.                   perror ( "failed to pipe" );
  13.                   exit( 1 );
  14.          }
  15.          if ( (pid = fork()) < 0 ){ /* 创建一个子进程 */
  16.                   perror ( "failed to fork " );
  17.                   exit( 1 );
  18.          }
  19.          else if ( pid > 0 ){
  20.                 close ( fd[0] ); /*父进程中关闭管道的读出端*/
  21.                  write (fd[1], "hello my son!\n", 14 ); /*父进程向管道写入数据*/
  22.                  exit ( 0);
  23.          }
  24.          else {
  25.                  close ( fd[1] ); /*子进程关闭管道的写入端*/
  26.                 len = read (fd[0], buf, BUFS ); /*子进程从管道中读出数据*/
  27.         if ( len < 0 ){
  28.                  perror ( "process failed when read a pipe " );
  29.                  exit( 1 );
  30.         }
  31.          else
  32.                  write(STDOUT_FILENO, buf, len); /*输出到标准输出*/
  33.                  exit(0);
  34.          }
  35. }
阅读(1688) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~