匿名管道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必须两端都打开的时候才能工作,否则阻塞。

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

  1. 【Linux 应用编程】进程管理 - 进程间通信IPC之管道 pipe 和 FIFO

    IPC(InterProcess Communication,进程间通信)是进程中的重要概念.Linux 进程之间常用的通信方式有: 文件:简单,低效,需要代码控制同步 管道:使用简单,默认阻塞 匿名 ...

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

    整理自网络 Unix IPC包括:管道(pipe).命名管道(FIFO)与信号(Signal) 管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道 ...

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

     无名管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信: 定义函数: int pipe(int f ...

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

    IPC进程间通信+管道Pipe                IPC(Inter-Process Communication,进程间通信).         管道用于进程间共享数据,事实上质是共享内存 ...

  5. IPC 进程间通信方式——管道

    进程间通信概述 数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间 共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到. 通知时间: ...

  6. linux中管道(pipe)一谈

    /*********************************************** 管道(pipe)是Linux上进程间通信的一种方式,其是半双工(数据流只能在一个方向上流动(还需要经过 ...

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

    我们先来说说进程间通信(IPC)的一般目的,大概有数据传输.共享数据.通知事件.资源共享和进程控制等.但是我们知道,对于每一个进程来说这个进程看到属于它的一块内存资源,这块资源是它所独占的,所以进程之 ...

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

    1. 管道概述及相关API应用 1.1 管道相关的关键概念 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管 ...

  9. 进程间通信和同步:pipe、FIFO、消息队列、信号量、共享内存、信号

    一.半双工管道(pipe) 关于管道详细介绍可参考http://www.cnblogs.com/nufangrensheng/p/3560130.html. 1.管道实现父子进程间通信实例: /* p ...

随机推荐

  1. Jenkins常用插件介绍

    摘要: 对于中小型运维团队,jenkins作为运维利器,可以解决很多工作中的痛点.基于UI的特性从而让使用者的入门成本很低,基于插件可以具备认证,记录,条件触发以及联动,让运维工程师可以将精力放在业务 ...

  2. windows server 2008 R2 Enterprise 防火墙开启允许远程桌面登录

    解决方法: 开始------ > 运行 ----- > gpedit.msc 打开“本地组策略编辑器”,按如下设置:计算机配置----->管理模板----->网络-----&g ...

  3. Validator自动验证与手动验证

    自动: public JResult projectAdd(@Valid Project project, BindingResult result) {Map<String,Object> ...

  4. windows安装npm教程

    1.在使用之前,先类掌握3个东西,明白它们是用来干什么的: npm:  nodejs 下的包管理器. webpack: 它主要用途是通过CommonJS 的语法把所有浏览器端需要发布的静态资源作相应的 ...

  5. 【原创】大数据基础之Kudu(5)kudu增加或删除目录/数据盘

    kudu加减数据盘不能直接修改配置fs_data_dirs后重启,否则会报错: Check failed: _s.ok() Bad status: Already present: FS layout ...

  6. python numpy 的用法—— bincount

    今天看脚本的时候遇到了几个不懂的用法,记录下来供日后查看: 1.numpy bincount 先上图: 如上所示:首先要求输入的数组不能包含负数: 该函数是计算非负元素的个数,如果数组中的最大值为10 ...

  7. VS2019 快捷键

    工欲善其事,必先利其器,整理了下VS最常用的快捷键,查看了不少资料,汇总了下,没有的自己补充,可以打印,用Excel编辑的. 可编辑版本下载:Excel文件下载 你可能需要查询其他的快捷键,MSDN介 ...

  8. springboot2.0集成webSocket

    WebSocket和http的区别? http协议是用在应用层的协议,他是基于tcp协议的,http协议建立链接也必须要有三次握手才能发送信息. http链接分为短链接,长链接,短链接是每次请求都要三 ...

  9. easyui-datagrid 编辑模式详解——combobox

    用于列表显示号了,需要改动某一列的值,而且根据每一行的数据去加载data数据,放在这个列中供别人选择 //-------------------- 代码可变区//---------- 数据定义区var ...

  10. Wxpython pannel切换

    演示效果 实现panel切换思路 1.创建所有在某个区域需要切换面板对象,设置为None self.panel_Celan1 = None self.panel_Celan2 = None self. ...