进程间通信--管道

进程间通信–管道

管道是一种最基本的 IPC 机制,作用于有有血缘关系的进程之间,完成数据传递。调用 pipe 系统函数即可创建一个管道,有如下特质:

  • 其本质是一个伪文件(实为内核缓冲区)
  • 由两个文件描述符引用,一个表示读端,一个表示写端
  • 规定数据从管道的写端流入管道,从读端流出

管道的原理:管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。管道的局限性如下:

  • 数据自己读不能自己写
  • 数据一旦被读走,便不再管道中存在,不可反复读取
  • 由于管道采用半双工通信方式。因此,数据只能在一个方向上流动
  • 只能在有公共祖先的进程间使用管道(匿名管道命名管道不需要进程间具备公共祖先)

匿名管道

在这里插入图片描述

  • 功能:创建一个无名管道
  • 参数:
    • fd:文件描述符数组,其中 fd[0] 表示读端,fd[1] 表示写端
  • 返回值:成功返回 0,失败返回错误代码

失败原因:

  • 文件描述符表满了,无法再创建文件描述符
  • 管道使用完成之后,需要及时关闭文件描述符

注意:

管道中的数据一旦被读取之后就相当于出队列了到底是谁先读到,就取决于谁先执行读文件的操作。
管道内置了同步互斥机制,不会出现两个管道一人读一半数据的情况

1. 多个进程同事去读写管道,数据不会发生错乱。
  1. 如果管道为空,尝试读,就会在read函数处阻塞;如果管道满了,尝试写,就会在write处阻塞。
#include <iostream>
#include <unistd.h>
#include <cstdlib>

int main(void)
{
    int pipefd[2];
    if (pipe(pipefd) == -1)
    {
        perror("pipe");
        return 1;
    }

    int ret = fork();
    if (ret < 0)
    {
        perror("fork");
        return 1;
    }
    else if (ret == 0) // child
    {
        close(pipefd[0]);
        write(pipefd[1], "Hello", 5);
        close(pipefd[1]);

        exit(EXIT_SUCCESS);
    }
    else // parent
    {
        close(pipefd[1]);
        char buf[1024] = {0};
        read(pipefd[0], buf, 1023);

        printf("child said: %s\n", buf);
    }


    return 0;
}

命名管道

命名管道与匿名管道最大的区别就是在于:

  • 使用匿名管道通信的进程必须得具有共同的祖先,而命名管道不用。

命名管道的创建

可以在 shell 中创建

$ mkfifo filename

也可以在程序里创建

int mkfifo(const char* filename, mode_t mode)

创建命名管道

int main(void)
{
    mkfifo("pipe", 0644);
    return 0;
}

命名管道和匿名管道的区别

  • 匿名管道由 pipe 函数创建并打开
  • 命名管道有 mkfifo 函数创建,打开用 open
  • 命名管道和匿名管道的打开方式不同外,其使用方式是相同的

?叮~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值