进程间通信之无名管道

进程间通信之无名管道

自信、冷静、专注。 —— TM熊的自我勉励

冲呀


linux进程间通信方式:

  • 无名管道
  • 命名管道;
  • 消息队列;
  • 信号;
  • 信号量;
  • 共享内存;
  • 网络通信;

本文介绍linux下进程间通信方式之一的无名管道。

概述

什么是管道?

想象下水管,水从一端流向另一端,正常情况下是不是只能从一端流入,一端流出。

水管

管道又分为:

  • 无名管道
  • 有名管道

即使对无名管道不是很了解,但是在你使用linux系统命令时应该经常接触到的,就是命令之间用于传递上个命令结果到下个命令作为参数的|符号:

ps -aux | grep init

而无名管道与有名管道最直观的区别在于有名管道能在文件系统中找到对应类型的文件,举个例子:

$ mkfifo /tmp/tpipe

$ ls -l /tmp/tpipe

prw-r--r-- 1 wotsen wotsen 0 Oct 25 10:20 /tmp/tpipe

其中查看文件类型时,前面的p标志就代表它是一个管道文件

在一个终端内进行写:

$ echo "hello pipe" > /tmp/tpipe

在另一个终端内进行读取:

$ cat /tmp/tpipe

hello pipe

无名管道

管道文件也是一种文件,那么我们写管道、读管道也就是读写文件。
无名管道,顾名思义则是没有名称的管道文件,只存在内存中,有名管道则能在文件系统内查看到其名称。

无名管道特性:

  • 无名管道具有半双工、单向的特性,只能一端写,一端读;
  • 无名管道仅仅用于有亲缘关系的父子进程之间,你可以理解为因为管道没有名称,所以只能通过子进程继承的方式从父进程获取管道的句柄(文件描述符)
  • linux中无名管道使用的场景非常多,例如绝大部分shell程序都支持管道,命令行中使用|方式将前一个命令的输出通过管道给到后一个命令。

管道的实现是在内存中分配的空间用于存储数据,但是使用时具有部分和普通文件相同的特性:文件描述符、read/write/fcntl可用,所以在实际的使用过程比较简单。

无名管道API

创建无名管道:

#include <unistd.h>

int pipe(int pipefd[2]);
  • int pipefd[2]:参数为2个长度的数组,用于存放管道创建成功时读和写的描述符,[0]用于读,[1]用于写;
  • 返回值0为成功,-1为异常。

Tips:如果不记得函数详细说明,可以使用man命令查看,ubuntu安装man手册:

apt-get install manpages-de  manpages-de-dev  manpages-dev glibc-doc manpages-posix-dev manpages-posix

管道文件描述符中[0]用于读,[1]用于写,这是由于无名管道的特性引起的(先入先出,半双工,那么得规定哪端入,哪端出),简单模型如下:
posix-ipc

不过实际使用中一般用于父子继承间通信,pipefd[2]父子进程各有一对:
podix-ipc-process

注意:在用于父子进程中通信时,确保父子进程仅有一方读,另一方写,不要父或子对同一个管道既可写又可读。如果父进程用于写入数据,子进程则用于读出数据,并且父进程应该将读端pipefd[0]关闭,子进程应该将写端pipefd[1]关闭。如果需要父子进程双向通信,应该另外创建一个管道(一对)。原因是无名管道是半双工的,避免同时读写造成数据混乱。

父子进程的双向通信模型:

双向模型

关闭描述符

和普通文件一样使用close()进行关闭:

int close(int fd);

close(pipefd[0]);
close(pipefd[1]);

管道读写:

前面说过,管道的读写同文件读写一样,使用read/write即可:

ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);

read(pipefd[0], buf, count);
write(pipefd[1], buf, count);

设置阻塞,非阻塞:

创建管道时默认是阻塞的,不过使用fcntl来设置,设置阻塞时将对应的标记为置为~O_NONBLOCK,非阻塞时为O_NONBLOCK

int fcntl(int fd, int cmd, ... /* arg */ );

bool set_fd_block(
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值