▋****1. 管道的概念

管道,又名「无名管理」,或「匿名管道」,管道是一种非常基本,也是使用非常频繁的IPC方式。

1.1 管道本质

  • 管道的本质也是一种文件,不过是伪文件,实际上是一块内核缓冲区,大小4K;
  • 管道创建以后会产生两个文件描述符,一个是读端,另一个是写端;
  • 管道里的数据只能从写端被写入,从读端被读出;

1.2 管道原理

管道是内核的一块缓冲区,更具体一些,是一个环形队列。数据从队列的一端写入数据,另一端读出,如下图示:

1.3 管道的优点

简单

1.4 管道的缺点

  • 只能单向通信,如果需要双向通信则需要建立两个管道;
  • 只能应用于具有血缘关系的进程,如父子进程;
  • 缓冲区大小受限,通常为1页,即4k;

▋****2. 管道的创建

管道创建三步曲:

a. 父进程调用pipe函数创建管道;

b. 父进程调用fork函数创建子进程;

c. 父进程关闭fd[0],子进程关闭fd[1];

具体如下图所示:

▋****3. 管道的读写行为

a. 管道的缓冲区大小固定为4k,所以如果管道内数据已经写满,则无法再写入数据,进程的write调用将阻塞,直到有足够的空间再写入数据;

b. 管道的读动作比写动作要快,数据一旦被读走了,管道将释放相应的空间,以便后续数据的写入。当所有的数据都读完之后,进程的read()调用将阻塞,直到有数据再次写入。

▋****4. 例程

父子间通信:

  1. 1#include <stdio.h>
  2. 2#include <sys/types.h>
  3. 3#include <unistd.h>
  4. 4#include <string.h>
  5. 5
  6. 6int main()
  7. 7{
  8. 8 int fd[2];
  9. 9 pid_t pid;
  10. 10 char buf[1024];
  11. 11 char *data = "hello world!";
  12. 12
  13. 13 /* 创建管道 */
  14. 14 if (pipe(fd) == -1) {
  15. 15 printf("ERROR: pipe create failed!\n");
  16. 16 return -1;
  17. 17 }
  18. 18
  19. 19 pid = fork();
  20. 20 if (pid == 0) {
  21. 21 /* 子进程 */
  22. 22 close(fd[1]); // 子进程读取数据,关闭写端
  23. 23 read(fd[0], buf, sizeof(buf)); // 从管道读数据
  24. 24 printf("child process read: %s\n", buf);
  25. 25 close(fd[0]);
  26. 26 } else if (pid > 0) {
  27. 27 /* 父进程 */
  28. 28 close(fd[0]); //父进程写数据,关闭读端
  29. 29 write(fd[1], data, strlen(data)); // 向管道写数据
  30. 30 printf("parent process write: %s\n", data);
  31. 31 close(fd[1]);
  32. 32 }
  33. 33
  34. 34 return 0;
  35. 35}

兄弟间通信:

  1. 1#include <stdio.h>
  2. 2#include <sys/types.h>
  3. 3#include <unistd.h>
  4. 4#include <string.h>
  5. 5#include <sys/wait.h>
  6. 6
  7. 7int main ()
  8. 8{
  9. 9 int fd[2];
  10. 10 int i = 0;
  11. 11 pid_t pid;
  12. 12 char buf[1024];
  13. 13 char *data = "hello world!";
  14. 14
  15. 15 /* 创建管道 */
  16. 16 if (pipe(fd) == -1) {
  17. 17 printf("ERROR: pipe create failed!\n");
  18. 18 return -1;
  19. 19 }
  20. 20
  21. 21 for (i = 0; i < 2; i++) {
  22. 22 pid = fork();
  23. 23 if (pid == -1) {
  24. 24 printf("ERROR: fork error!\n");
  25. 25 return -1;
  26. 26 } else if (pid == 0) {
  27. 27 break;
  28. 28 }
  29. 29 }
  30. 30
  31. 31 /* 通过i来判断创建的子进程及父进程 */
  32. 32 if (i == 0) {
  33. 33 /* 第一个子进程,兄进程 */
  34. 34 close(fd[0]); // 兄进程向弟进程写数据,关闭读端
  35. 35 write(fd[1], data, strlen(data));
  36. 36 printf("elder brother send: %s\n", data);
  37. 37 close(fd[1]);
  38. 38 } else if (i == 1) {
  39. 39 /* 第二个子进程,弟进程 */
  40. 40 close(fd[1]);
  41. 41 read(fd[0], buf, sizeof(buf));
  42. 42 printf("younger brother receive: %s\n", buf);
  43. 43 close(fd[0]);
  44. 44 } else {
  45. 45 /* 父进程 */
  46. 46 close(fd[0]);
  47. 47 close(fd[1]);
  48. 48 for (i = 0; i < 2; i++) {
  49. 49 wait(NULL);
  50. 50 }
  51. 51 }
  52. 52
  53. 53 return 0;
  54. 54}

更多精彩内容,请关注公众号良许Linux,公众内回复1024可免费获得5T技术资料,包括:Linux,C/C++,Python,树莓派,嵌入式,Java,人工智能,等等。公众号内回复进群,邀请您进高手如云技术交流群。


公众号:良许Linux

有收获?希望老铁们来个三连击,给更多的人看到这篇文章

Linux系统编程—有名管道的更多相关文章

  1. linux系统编程之管道(三)

    今天继续研究管道的内容,这次主要是研究一下命名管道,以及与之前学过的匿名管道的区别,话不多说,进入正题: 所以说,我们要知道命名管道的作用,可以进行毫无关系的两个进程间进行通讯,这是匿名管道所无法实现 ...

  2. linux系统编程之管道(三):命令管道(FIFO)

    一,匿名管道PIPE局限性 管道的主要局限性正体现在它的特点上: 只支持单向数据流: 只能用于具有亲缘关系的进程之间: 没有名字: 管道的缓冲区是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配 ...

  3. linux系统编程之管道(二):管道读写规则

    一,管道读写规则 当没有数据可读时 O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止. O_NONBLOCK enable:read调用返回-1,errn ...

  4. linux系统编程之管道(一):匿名管道(pipe)

    一,什么是管道 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道: 只能用于父子进程或者兄弟进程之间(具有 ...

  5. linux系统编程之管道(二)

    今天继续研究管道,话不多说,言归正传: 对于管道,有一定的读写规则,所以这里主要是对它的规则进行探讨,具体规则如下: 规则一: 下面用程序来验证下,还是用上节学的子进程写数据,父进程读取数据的例子,只 ...

  6. Linux 系统编程 学习:02-进程间通信1:Unix IPC(1)管道

    Linux 系统编程 学习:02-进程间通信1:Unix IPC(1)管道 背景 上一讲我们介绍了创建子进程的方式.我们都知道,创建子进程是为了与父进程协作(或者是为了执行新的程序,参考 Linux ...

  7. Linux系统编程@进程通信(一)

    进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统 ...

  8. linux系统编程之框架

    linux系统编程之框架: 1. 进程 1.1 进程概念 1.1.1 PCB 1.1.2 环境变量 1.2 进程控制 1.3 进程间通信 1.3.1 管道 1.3.2 有名管道 1.3.3 共享内存 ...

  9. Linux 系统编程 学习:05-进程间通信2:System V IPC(2)

    Linux 系统编程 学习:05-进程间通信2:System V IPC(2) 背景 上一讲 进程间通信:System V IPC(1)中,我们介绍了System IPC中有关消息队列.共享内存的概念 ...

随机推荐

  1. lidar激光雷达领域的分类

    lidar领域可以按分为以下五方面: 激光雷达系统与装备 激光雷达系统与开发 激光雷达光源 激光雷达探测 多光谱激光雷达系统 单光子激光雷达系统 低成本RGB-D距离传感器 激光雷达元器件及装备等 激 ...

  2. F - 丘 (欧拉函数)

    Chinese people think of '8' as the lucky digit. Bob also likes digit '8'. Moreover, Bob has his own ...

  3. 面试【JAVA基础】类加载机制

    1.类加载过程 1.1.加载 查找和导入class文件. 1.2.链接 验证 检验载入的class文件的正确性,完整性. 准备 给类的静态变量分配存储空间,会赋对象类型的默认值. 解析 将class常 ...

  4. 阿里面试官:HashMap 熟悉吧?好的,那就来聊聊 Redis 字典吧!

    最近,小黑哥的一个朋友出去面试,回来跟小黑哥抱怨,面试官不按套路出牌,直接打乱了他的节奏. 事情是这样的,前面面试问了几个 Java 的相关问题,我朋友回答还不错,接下来面试官就问了一句:看来 Jav ...

  5. Ajax请求携带Cookie

    目录 xhr ajax cookie跨域处理 客户端 服务端 服务端设置跨域的几种方式 方式一 重写addCorsMappings方法 方式二 对单个接口处理 方式三 @CrossOrigin注解 方 ...

  6. python爬取拉勾网职位信息-python相关职位

    import requestsimport mathimport pandas as pdimport timefrom lxml import etree url = 'https://www.la ...

  7. 原生JDK网络编程BIO

    服务端提供IP和监听端口,客户端通过连接操作想服务端监听的地址发起连接请求,通过三次握手连接,如果连接成功建立,双方就可以通过套接字进行通信. 传统的同步阻塞模型开发中,ServerSocket负责绑 ...

  8. 借助Java的JDBC自制“DBMS”管理操作数据库

    package jdbc; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; imp ...

  9. Hexo博客迁移

    Hexo用户指南 - 博客迁移 GitHub+Hexo搭建博客的过程比较平滑,但是它的配置却非常耗时,一旦电脑出现问题或者需要在另外一台电脑上写博客,那么Hexo博客的迁移非常就让人头疼.下面参考其他 ...

  10. ThinkPHP6.0 多应用模式 部署 Layuiadmin 单页版

    TP6.0中的路由省略应用名只能用入口文件绑定应用 和 域名绑定应用,经过测试,最后得出域名绑定应用是最合适的部署方式.如果有更好的部署方案,欢迎分享.QQ:23426945 1. 下载TP6.0,引 ...