简述Linux进程间通信之管道pipe(下)

  上篇文章的简述,我相信大家对管道的概念有了模糊的认识,本文通过代码实例来强化对管道的理解.

  创建管道主要用到pipe函数,pipe的原型如下:

一、函数原型

  #include <unistd.h>

  int pipe(int pipefd[2]);

  参数:一个整型数组,管道创建成功后,pipefd[0]表示管道的读端,pipefd[1]表示管道的写端.

  成功返回0,失败返回-1,同时errno被设置.

二、父子进程通信

  上文中,我们描述了父子进程通过管道来进行通信的整个过程,现在我们用C语言来实现:

#include<stdio.h>
#include<unistd.h>
int main(){
    int fds[2] = {0};
    //1.创建管道
    if(pipe(fds)==-1){
        perror("pipe");
        return 1;
    }
    //2.fork子进程
    pid_t pid = fork();
    if(pid > 0){        //father
        //3.父进程关闭读端,向写端写入数据
        close(fds[0]);
        char buff[1024]={0};
        printf("parent to child#");
        fflush(stdout);
        ssize_t s = read(0,buff,sizeof(buff)-1);
        buff[s-1] = 0;
        write(fds[1],buff,s);
        close(fds[1]);
    }else if(pid==0){   //child
        //3.子进程关闭写端,从读端读出数据
        close(fds[1]);
        char buff[1024]={0};
        ssize_t s = read(fds[0],buff,sizeof(buff));
        printf("child to receive#%s\n",buff);
        close(fds[0]);
    }else{
        perror("fork");
        return 2;
    }
    wait(NULL); //回收子进程
    return 0;
}

  上述代码中,我们展示的是父子进程普通的通信情况,除了正常情况之外,我们还需考虑四种异常情况:

三、四种情况

  为了节省文章篇幅,代码部分省略,读者可以自行测试.

  1.父进程不断向管道中写数据,子进程不从管道中读取数据,子进程fds[0]读端保持开启.

  这种情况将导致管道被写满,同时父进程被阻塞,直到管道中有空位置.

  2.父进程不断向管道中写数据,子进程不从管道中读取数据,子进程关闭了fds[0]读端.

  这种情况下,父进程会收到SIGPIPE信号,进而被终止.

  3.父进程向管道中写了一些数据,子进程不断从管道中读取数据,父进程fds[1]写端保持开启.

  这种情况下,子进程将管道中数据读取完毕之后,会进入阻塞状态.直到管道中有新数据产生.

  4.父进程向管道中写了一些数据,子进程不断从管道中读取数据,父进程关闭了fds[1]写端.

  这种情况下,子进程会读完管道中数据,最后read返回0,就像读到文件末尾一样.

时间: 2024-10-25 15:29:24

简述Linux进程间通信之管道pipe(下)的相关文章

Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)

整理自网络 Unix IPC包括:管道(pipe).命名管道(FIFO)与信号(Signal) 管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信: 实现机制: 管道是由内核管理的一个缓冲区,相当于我们放入内存中的一个纸条.管道的一端连接一个进程的输出.这个进程会向管道中放入信息.管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息.一个缓冲区不需要很大,它被设计成为环形的数据结构,以便管

Linux 进程间通信之管道(pipe),(fifo)

 无名管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信: 定义函数: int pipe(int filedes[2]) filedes[0]为管道里的读取端 filedes[1]则为管道的写入端. 实现机制: 管道是由内核管理的一个缓冲区,相当于我们放入内存中的一个纸条.管道的一端连接一个进程的输出.这个进程会向管道中放入信息.管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息.一个缓

简述Linux进程间通信之命名管道FIFO

上文聊到管道(pipe),可以使有亲缘关系的进程间进行通信. 对于没有亲缘关系的进程如何通信?本文来聊一聊命名管道FIFO. 一.概念 命名管道FIFO,提供一个路径名与之关联,以文件形式存储于文件系统中. 一个进程以r方式打开,另一个程序以w方式打开,即可在两个进程之间建立管道. 通过以fifo文件作为媒介,可以使任意两个进程通过该文件进行通信. 命名管道(fifo)特性与管道(pipe)类似,不必赘述. 下面我们看FIFO如何进行进程间通信,首先来介绍一下所用到的函数: 二.函数原型 #in

进程间通信(4) - 管道(pipe)

1. 前言 本篇文章的所有例子,基于RHEL6.5平台.本篇只介绍管道(匿名管道/普通管道),命名管道在后续文章中会介绍. 2.管道特性 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: **管道是半双工的,数据只能向一个方向流动,一端输入,另一端输出.需要双方通信时,需要建立起两个管道. **管道分为普通管道和命名管道.普通管道位于内存,只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程).命名管道位于文件系统,没有亲缘关系的进程间只要知道管道名也可以通讯. **管道也是文

进程间通信之管道--pipe和fifo使用

匿名管道pipe 函数原型: #include <unistd.h> int pipe(int fildes[2]); 参数说明 fildes是我们传入的数组,也是一个传出参数.fildes[0]是读端,fildes[1]是写端. 返回值 成功调用返回0. 失败调用返回-1且设置errno. 实例 现在实现一个用父进程读,子进程写的管道例子. int main(int argc, char const *argv[]) { int pipefd[2]; pipe(pipefd); pid_t

【IPC第二个进程间通信】管道Pipe

IPC进程间通信+管道Pipe         IPC(Inter-Process Communication,进程间通信).         管道用于进程间共享数据,事实上质是共享内存.经常使用IPC之中的一个.管道不仅能够用于本机进程间通信,还可实现跨网络进程间通信,如同Socket通信,管道相同封装计算机底层网络实现,提供一个良好的API接口.                1.管道(Pipe):        管道分为匿名管道和命名管道.        匿名管道仅仅能用于父子进程间通信

Linux进程间通信之管道

1,进程间通信 (IPC ) Inter-Process Communication 比较好理解概念的就是进程间通信就是在不同进程之间传播或交换信息. 2,linux下IPC机制的分类:管道.信号.共享内存.消息队列.信号量.套接字 3,这篇主要说说管道:本质是文件,其他理论什么的网上已经有一大堆了,我就只写一点用法吧. 3.1 特点 1)管道是最古老的IPC,但目前很少使用     2)以文件做交互的媒介,管道分为有名管道和无名管道     3)历史上的管道通常是指半双工管道 3.2 管道:有

Linux进程间通信:管道

提到进程间通信,我们需要先了解一下进程是什么: 其实在Linux下,早期的Linux为了实现多个程序之间的交替操作,出现了进程的概念.为的就是维护操作系统整个的运行逻辑.并发就是进程间的交替执行. 进程是程序的动态实例. 进程并发运行的环境中,多个进程之间存在如下竞争和合作的关系: -          进程中的资源争用(间接作用) 当并发进程竞争使用同一个资源时,它们之间就会发生冲突.为了避免冲突,当一个进程获得资源时,另一个进程必须等待.这种情况需要通过互斥机制来解决. -         

Linux进程间通信-匿名管道

前面我们讲了进程间通信的一种方式,共享内存.下面看一看另一种机制,匿名管道.1.什么是管道管道是一个进程的数据流到另一个进程的通道,即一个进程的数据输出作为另一个进程的数据输入,管道起到了桥梁的作用.比如,在shell中输入命令:ls -l|grep string,ls和grep是两个进程,"|"符号表示管道,意思是执行ls -l进程,并将输出结果result_1,作为grep string进程的输入result_0,grep进程将result_0中存在字符串string的信息打印到屏