进程间通信之管道--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 pid = fork();
    if (pid == 0)
    {
        //子进程写
        //关闭读
        close(pipefd[0]);
        write(pipefd[1], "hello fuck!", 15);
        sleep(1);
    }
    else if (pid > 0)
    {
        //关闭写
        close(pipefd[1]);
        char buf[16] = {0};
        read(pipefd[0], buf, sizeof(buf));
        printf("%s\n", buf);
    }
    return 0;
}

在这个程序执行之后,父进程会读取到子进程所写的数据。在这个简单的例子中看不到什么坑点。

坑点

在亲缘进程中,我们使用管道要注意以下几点。就拿父子进程作为例子:

当前情况是,双方都掌控有读写端,都可以操作。

fork之后,共享管道的读写端。我们一方读一方写,最好要自己指定方向,使数据沿着固定的方向流动。如:

我们这样就指定了子进程来写,父进程来读。也就是说,我们仅仅只需要在代码上加上两个Close就可以完成这个功能:close父进程的写端,close子进程的读端。

如果我们不这样会发生什么?

坑点总结

  • 写进程:

    • 读端全部关闭: 在写进程中,如果内核发现读端全部关闭,内核会认为没有人会来读数据,因此杀死写进程,通过发出的SIGPIPE。
    • 读端并未全部关闭: 在写进程中,如果内核发现读端并未全部关闭,会写入数据直到管道满,write会阻塞,等待数据被读取,有地方可写会再写。
  • 读进程:
    • 写端全部关闭: 在读进程中,写端全部关闭,会读取完管道中的数据,然后返回0,表示读到末尾了。和文件读取一致。
    • 写端并未全部关闭: 在读进程中,写端并未全部关闭,如果管道有数据就会读取,没有数据就会阻塞等待写端的写入。

其中特别要注意,写端没有全关闭的时候并且无数据的时候,读端会阻塞等待写。

Note

  • 数据不能反复读取,读了就会被取走。
  • 半双工。
  • 有亲缘关系进程间使用。
  • 可以通过ulimit -a指令查看各种块的限制大小。其中pipe size就是管道的大小。

FIFO有名管道

此管道突破了匿名管道只能亲缘间通信的限制。

可以用命令直接创建一个有名管道:

mkfifo myfifo

就可以看到一个myfifo管道了。Linux下一切皆文件,打开这个管道和打开文件一样,用open函数即可。

下面写了一个读程序和写程序,可以参考:

//读进程,读了就会被取走,可同时执行两次看结果
int main(int argc, char const *argv[])
{
    int fd = open("myfifo", O_RDONLY);
    while (1)
    {
        char buf[128] = {0};
        int ret = read(fd, buf, sizeof(buf));   //如果写端被关闭,读端返回0,就是读到末尾了。
        if (ret)    printf("%s\n", buf);
        else break;
    }
    return 0;
}

写程序如下:

//写进程。
int main(int argc, char const *argv[])
{
    int fd = open("myfifo", O_WRONLY);
    int num = 1;
    while (1)
    {
        char buf[128] = {0};
        sprintf(buf, "read data:%04d", num++);
        write(fd, buf, strlen(buf));
        sleep(1);
    }
    return 0;
}

和普通文件操作并无区别。

Note

假设我们先执行读程序,还没执行写程序时,会阻塞,直到写端被打开。

同理,我们先执行写程序,还没执行读程序时,也会阻塞,知道读端被打开。

以上告诉我们,fifo必须两端都打开的时候才能工作,否则阻塞。

原文地址:https://www.cnblogs.com/love-jelly-pig/p/10053054.html

时间: 2024-12-11 05:06:09

进程间通信之管道--pipe和fifo使用的相关文章

进程间通信 管道 (pipe,FiFO)

管道的运行原理 管道是一种最基本的IPC机制,由pipe函数创建 #include <unistd.h> int pipe(int _pipe[2]); 调用pipe函数时在内核中开辟一块缓冲区用于通信,它有一个读端和一个写端,通过filedes参数传出给程序两个文件描述符,filedes[0]指向管道的读端,filedes[1]指向管道的写端.管道就像一个打开的文件,通过read(filedes[0]);或者write(filedes[1]):向这个文件读写数据,其实是在读写内核缓冲区.pi

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

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

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

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

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

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

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

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

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

上篇文章的简述,我相信大家对管道的概念有了模糊的认识,本文通过代码实例来强化对管道的理解. 创建管道主要用到pipe函数,pipe的原型如下: 一.函数原型 #include <unistd.h> int pipe(int pipefd[2]); 参数:一个整型数组,管道创建成功后,pipefd[0]表示管道的读端,pipefd[1]表示管道的写端. 成功返回0,失败返回-1,同时errno被设置. 二.父子进程通信 上文中,我们描述了父子进程通过管道来进行通信的整个过程,现在我们用C语言来实

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

我们先来说说进程间通信(IPC)的一般目的,大概有数据传输.共享数据.通知事件.资源共享和进程控制等.但是我们知道,对于每一个进程来说这个进程看到属于它的一块内存资源,这块资源是它所独占的,所以进程之间的通信就会比较麻烦,原理就是需要让不同的进程间能够看到一份公共的资源.所以交换数据必须通过内核,在内核中开辟?块缓冲区,进程1把数据从?户空间 拷到内核缓冲区,进程2再从内核缓冲区把数据读?,内核提供的这种机制称为进程间通信.一般我们采用的进程间通信方式有 管道(pipe)和有名管道(FIFO)

进程间通信IPC—匿名管道(pipe)和命名管道(fifo)

管道内部如何实现-大小,组织方式,环形队列? 一.进程间通信有多种方式,本文主要讲解对管道的理解.管道分为匿名管道和命名管道. (1)管道( pipe ):又称匿名管道.是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系通常是指父子进程关系. (2)命名管道 (named pipe或FIFO) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信. 二.管道 1. 管道的特点: (1)管道是半双工的,数据只能向一个方向流动:双方通信时,需要

Unix/Linux进程间通信(二):匿名管道、有名管道 pipe()、mkfifo()

1. 管道概述及相关API应用 1.1 管道相关的关键概念 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道: 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程): 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中. 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出.