09-进程间通信-无名管道(父子进程间)

[TOC]
(来自:http://blog.chinaunix.net/uid-26833883-id-3227144.html

一、什么是管道?

管道是单向的、先进先出的,它把一个进程的输出和另一个进程的输入连接在一起。一个进程(写进程)在管道的尾部写入数据,另一个进程(读进程)从管道的头部读出数据。

二、管道的分类

管道包括无名管道和命名管道两种,前者用于父进程和子进程间的通信,后者可用于运行于同一系统中的任意两个进程间的通信。

三、管道特点


  1. 管道通讯是单向的,有固定的读端和写端。
  2. 数据被进程从管道读出后,在管道中该数据就不存在了。
  3. 当进程去读取空管道的时候,进程会阻塞。
  4. 当进程往满管道写入数据时,进程会阻塞。
  5. 管道容量为64KB(#define PIPE_BUFFERS 16
    include/linux/pipe_fs_i.h)

在Linux系统中,无名管道一旦创建完成后,操作无名管道
等同于操作文件。无名管道的读端被视作一个文件;无名管
道的写端也被视作一个文件

四、无名管道操作函数pipe

  1. 创建无名管道pipe函数
    头文件:《unistd.h》
    函数原型:int pipe(int pipefd[2]) ;
    函数功能:创建一个可用于进程间通信的无名管道;
    函数参数:pipefd[0]:读段文件描述符;pipefd[1]:写端文件描述符;
    函数返回值:成功:返回0;失败:返回-1;
    注意:这无名管道通信的操作方式其实也跟操作文件一样。父子进程对管道分别有自己的读写通道,把无关的读端或写段关闭。
  2. 无名管道的读写规则探究

    1. A.从管道中读取数据
      <1>写端不存在时,此时则认为已经读到了数据的末尾,读函数返回的读出字节数为0;
      <2>写端存在时,如果请求的字节数目大于PIPE_BUF(ubuntu操作系统为65536),则返回管道中现有的数据字节数,如果请求的字节数目不大于PIPE_BUF,则放回管道中现有数据字节数(此时,管道中数据量小于请求的数据量);或者返回请求的字节数(此时,管道中数据量不小于请求的数据量)
      从以上验证我们可以看到:
      <1>当写端存在时,管道中没有数据时,读取管道时将阻塞
      <2>当读端请求读取的数据大于管道中的数据时,此时读取管道中实际大小的数据
      <3>当读端请求读取的数据小于管道中的数据时,此时放回请求读取的大小数据;
    2. 向管道中写入数据:
      向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。当管道满时,读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。
    3. 注意:只有管道的读端存在时,向管道中写入数据才有意义。否则,向管道中写入数据的进程将收到内核传来的SIGPIPE信号,应用程序可以处理该信号,也可以忽略(默认动作则是使应用程序终止)。
      探究发现,当管道数据满时,此时再向管道写数据,写端将阻塞。当读端不存在时,写端写数据,内核将向其发送SIGPIPE信号,默认是终止进程。
#include <unistd.h>
#include <sys/wait.h>

int main( int argc , char **argv ) {

        int fd[2] ;
        int ret = pipe(fd) ;
        if( 0>ret )
                printf( "creat pipe fail!\n" ) ;
        pid_t pid = fork() ;
        if( pid>0 ) {
        /*父子进程对管道分别有自己的读写通道,把无关的读端或写段关闭。*/
                wait(NULL) ;
                close( fd[1] ) ;
                printf(" father start read \n") ;
                char buf[5] = {0} ;
                read( fd[0] , buf , 5 ) ;
                printf( "father read 1  is : %s\n",buf ) ;
                strcpy( buf,"") ;
                read( fd[0] , buf , 5 ) ;
                printf( "father read 2 is : %s \n",buf ) ;
                close(fd[0]) ;
                exit(0) ;
        }else{
        /*父子进程对管道分别有自己的读写通道,把无关的读端或写段关闭。*/
                printf("this is son write .\n") ;
                close( fd[0]) ;
                write( fd[1] , "good" , 5 ) ;
                close( fd[1] ) ;
                printf( "son write succeed \n" ) ;
                exit(0) ;
        }
        return 0 ;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值