爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      linux管道pipe详解

      首页 知识中心 其他 文章详情页

      linux管道pipe详解

      2025-02-25 08:54:43 阅读次数:13

      lt,管道,进程

      管道

      管道的概念:

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

      1. 其本质是一个伪文件(实为内核缓冲区)

      2. 由两个文件描述符引用,一个表示读端,一个表示写端。

      3. 规定数据从管道的写端流入管道,从读端流出。

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

      管道的局限性:

      ① 数据自己读不能自己写。

      ② 数据一旦被读走,便不在管道中存在,不可反复读取。

      ③ 由于管道采用半双工通信方式。因此,数据只能在一个方向上流动。

      ④ 只能在有公共祖先的进程间使用管道。

      常见的通信方式有,单工通信、半双工通信、全双工通信。

      pipe函数

      创建管道

          int pipe(int pipefd[2]); 成功:0;失败:-1,设置errno

      函数调用成功返回r/w两个文件描述符。无需open,但需手动close。规定:fd[0] → r; fd[1] → w,就像0对应标准输入,1对应标准输出一样。向管道文件读写数据其实是在读写内核缓冲区。

      管道创建成功以后,创建该管道的进程(父进程)同时掌握着管道的读端和写端。如何实现父子进程间通信呢?通常可以采用如下步骤:

      linux管道pipe详解

      1. 父进程调用pipe函数创建管道,得到两个文件描述符fd[0]、fd[1]指向管道的读端和写端。

      2. 父进程调用fork创建子进程,那么子进程也有两个文件描述符指向同一管道。

      3. 父进程关闭管道读端,子进程关闭管道写端。父进程可以向管道中写入数据,子进程将管道中的数据读出。由于管道是利用环形队列实现的,数据从写端流入管道,从读端流出,这样就实现了进程间通信。

          练习:父子进程使用管道通信,父写入字符串,子进程读出并,打印到屏幕。 【pipe.c】

      思考:为甚么,程序中没有使用sleep函数,但依然能保证子进程运行时一定会读到数据呢?

       

       
       
      1. #include <unistd.h>

      2.  
      3. #include <string.h>

      4.  
      5. #include <stdlib.h>

      6.  
      7. #include <stdio.h>

      8.  
      9. #include <sys/wait.h>

      10.  
      11.  
      12. void sys_err(const char *str)

      13.  
      14. {

      15.  
      16. perror(str);

      17.  
      18. exit(1);

      19.  
      20. }

      21.  
      22.  
      23. int main(void)

      24.  
      25. {

      26.  
      27. pid_t pid;

      28.  
      29. char buf[1024];

      30.  
      31. int fd[2];

      32.  
      33. char *p = "test for pipe\n";

      34.  
      35.  
      36. if (pipe(fd) == -1)

      37.  
      38. sys_err("pipe");

      39.  
      40.  
      41. pid = fork();

      42.  
      43. if (pid < 0) {

      44.  
      45. sys_err("fork err");

      46.  
      47. } else if (pid == 0) {

      48.  
      49. close(fd[1]);

      50.  
      51. int len = read(fd[0], buf, sizeof(buf));

      52.  
      53. write(STDOUT_FILENO, buf, len);

      54.  
      55. close(fd[0]);

      56.  
      57. } else {

      58.  
      59. close(fd[0]);

      60.  
      61. write(fd[1], p, strlen(p));

      62.  
      63. wait(NULL);

      64.  
      65. close(fd[1]);

      66.  
      67. }

      68.  
      69.  
      70. return 0;

      71.  
      72. }

       

      管道的读写行为

          使用管道需要注意以下4种特殊情况(假设都是阻塞I/O操作,没有设置O_NONBLOCK标志):

      1. 如果所有指向管道写端的文件描述符都关闭了(管道写端引用计数为0),而仍然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就像读到文件末尾一样。

      2. 如果有指向管道写端的文件描述符没关闭(管道写端引用计数大于0),而持有管道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。

      3. 如果所有指向管道读端的文件描述符都关闭了(管道读端引用计数为0),这时有进程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。当然也可以对SIGPIPE信号实施捕捉,不终止进程。具体方法信号章节详细介绍。

      4. 如果有指向管道读端的文件描述符没关闭(管道读端引用计数大于0),而持有管道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时再次write会阻塞,直到管道中有空位置了才写入数据并返回。

      总结:

      ① 读管道: 1. 管道中有数据,read返回实际读到的字节数。

      2. 管道中无数据:

      (1) 管道写端被全部关闭,read返回0 (好像读到文件结尾)

        (2) 写端没有全部被关闭,read阻塞等待(不久的将来可能有数据递达,此时会让出cpu)

          ② 写管道: 1. 管道读端全部被关闭, 进程异常终止(也可使用捕捉SIGPIPE信号,使进程不终止)

      2. 管道读端没有全部关闭:

      (1) 管道已满,write阻塞。

      (2) 管道未满,write将数据写入,并返回实际写入的字节数。

          练习:使用管道实现父子进程间通信,完成:ls | wc –l。假定父进程实现ls,子进程实现wc。

      ls命令正常会将结果集写出到stdout,但现在会写入管道的写端;wc –l 正常应该从stdin读取数据,但此时会从管道的读端读。      【pipe1.c】

       

       
       
      1. #include <stdio.h>

      2.  
      3. #include <unistd.h>

      4.  
      5. #include <sys/wait.h>

      6.  
      7.  
      8. int main(void)

      9.  
      10. {

      11.  
      12. pid_t pid;

      13.  
      14. int fd[2];

      15.  
      16.  
      17. pipe(fd);

      18.  
      19. pid = fork();

      20.  
      21.  
      22. if (pid == 0) { //child

      23.  
      24. close(fd[1]); //子进程从管道中读数据,关闭写端

      25.  
      26. dup2(fd[0], STDIN_FILENO); //让wc从管道中读取数据

      27.  
      28. execlp("wc", "wc", "-l", NULL); //wc命令默认从标准读入取数据

      29.  
      30.  
      31. } else {

      32.  
      33.  
      34. close(fd[0]); //父进程向管道中写数据,关闭读端

      35.  
      36. dup2(fd[1], STDOUT_FILENO); //将ls的结果写入管道中

      37.  
      38. execlp("ls", "ls", NULL); //ls输出结果默认对应屏幕

      39.  
      40. }

      41.  
      42.  
      43. return 0;

      44.  
      45. }

      46.  
      47.  
      48.  
      49.  
      50.  
      51.  
      52. /*

      53.  
      54. * 程序不时的会出现先打印$提示符,再出程序运行结果的现象。

      55.  
      56. * 这是因为:父进程执行ls命令,将输出结果给通过管道传递给

      57.  
      58. * 子进程去执行wc命令,这时父进程若先于子进程打印wc运行结果

      59.  
      60. * 之前被shell使用wait函数成功回收,shell就会先于子进程打印

      61.  
      62. * wc运行结果之前打印$提示符。

      63.  
      64. * 解决方法:让子进程执行ls,父进程执行wc命令。或者在兄弟进程间完成。

      65.  
      66. */

      67.  


       

       

      程序执行,发现程序执行结束,shell还在阻塞等待用户输入。这是因为,shell → fork → ./pipe1, 程序pipe1的子进程将stdin重定向给管道,父进程执行的ls会将结果集通过管道写给子进程。若父进程在子进程打印wc的结果到屏幕之前被shell调用wait回收,shell就会先输出$提示符。

          练习:使用管道实现兄弟进程间通信。 兄:ls  弟: wc -l  父:等待回收子进程。

      要求,使用“循环创建N个子进程”模型创建兄弟进程,使用循环因子i标示。注意管道读写行为。 【pipe2.c】

       

       
       
      1. #include <stdio.h>

      2.  
      3. #include <unistd.h>

      4.  
      5. #include <sys/wait.h>

      6.  
      7.  
      8. int main(void)

      9.  
      10. {

      11.  
      12. pid_t pid;

      13.  
      14. int fd[2], i;

      15.  
      16.  
      17. pipe(fd);

      18.  
      19.  
      20. for (i = 0; i < 2; i++) {

      21.  
      22. if((pid = fork()) == 0) {

      23.  
      24. break;

      25.  
      26. }

      27.  
      28. }

      29.  
      30.  
      31. if (i == 0) { //兄

      32.  
      33. close(fd[0]); //写,关闭读端

      34.  
      35. dup2(fd[1], STDOUT_FILENO);

      36.  
      37. execlp("ls", "ls", NULL);

      38.  
      39. } else if (i == 1) { //弟

      40.  
      41. close(fd[1]); //读,关闭写端

      42.  
      43. dup2(fd[0], STDIN_FILENO);

      44.  
      45. execlp("wc", "wc", "-l", NULL);

      46.  
      47. } else {

      48.  
      49. close(fd[0]);

      50.  
      51. close(fd[1]);

      52.  
      53. for(i = 0; i < 2; i++) //两个儿子wait两次

      54.  
      55. wait(NULL);

      56.  
      57. }

      58.  
      59.  
      60. return 0;

      61.  
      62. }


       

       

          测试:是否允许,一个pipe有一个写端,多个读端呢?是否允许有一个读端多个写端呢? 【pipe3.c】

       

       
       
      1. #include <stdio.h>

      2.  
      3. #include <unistd.h>

      4.  
      5. #include <sys/wait.h>

      6.  
      7. #include <string.h>

      8.  
      9. #include <stdlib.h>

      10.  
      11.  
      12. int main(void)

      13.  
      14. {

      15.  
      16. pid_t pid;

      17.  
      18. int fd[2], i, n;

      19.  
      20. char buf[1024];

      21.  
      22.  
      23. int ret = pipe(fd);

      24.  
      25. if(ret == -1){

      26.  
      27. perror("pipe error");

      28.  
      29. exit(1);

      30.  
      31. }

      32.  
      33.  
      34. for(i = 0; i < 2; i++){

      35.  
      36. if((pid = fork()) == 0)

      37.  
      38. break;

      39.  
      40. else if(pid == -1){

      41.  
      42. perror("pipe error");

      43.  
      44. exit(1);

      45.  
      46. }

      47.  
      48. }

      49.  
      50.  
      51. if (i == 0) {

      52.  
      53. close(fd[0]);

      54.  
      55. write(fd[1], "1.hello\n", strlen("1.hello\n"));

      56.  
      57. } else if(i == 1) {

      58.  
      59. close(fd[0]);

      60.  
      61. write(fd[1], "2.world\n", strlen("2.world\n"));

      62.  
      63. } else {

      64.  
      65. close(fd[1]); //父进程关闭写端,留读端读取数据

      66.  
      67. // sleep(1);

      68.  
      69. n = read(fd[0], buf, 1024); //从管道中读数据

      70.  
      71. write(STDOUT_FILENO, buf, n);

      72.  
      73.  
      74. for(i = 0; i < 2; i++) //两个儿子wait两次

      75.  
      76. wait(NULL);

      77.  
      78. }

      79.  
      80.  
      81. return 0;

      82.  
      83. }

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.csdn.net/bandaoyu/article/details/111559229,作者:bandaoyu,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:【链表】判断两个单链表是否相交+找到第一个交点|判断两个链表是否有环

      下一篇:使用LRU加速python应用

      相关文章

      2025-05-19 09:04:22

      loki仿函数原理

      loki仿函数原理

      2025-05-19 09:04:22
      lt , void
      2025-05-16 09:15:17

      多源BFS问题(1)_01矩阵

      多源BFS问题(1)_01矩阵

      2025-05-16 09:15:17
      lt , 矩阵 , 遍历
      2025-05-16 09:15:17

      BFS解决拓扑排序(1)_课程表

      BFS解决拓扑排序(1)_课程表

      2025-05-16 09:15:17
      lt , 课程 , 队列
      2025-05-16 09:15:17

      BFS解决最短路问题(4)_为高尔夫比赛砍树

      BFS解决最短路问题(4)_为高尔夫比赛砍树

      2025-05-16 09:15:17
      BFS , lt , 复杂度 , 算法
      2025-05-16 09:15:10

      Linux系统基础-进程信号超详细讲解

      Linux系统基础-进程信号超详细讲解

      2025-05-16 09:15:10
      kill , 信号 , 命令 , 进程
      2025-05-16 09:15:10

      52.介绍AOP有几种实现方式

      52.介绍AOP有几种实现方式

      2025-05-16 09:15:10
      gt , lt , Spring
      2025-05-16 09:15:10

      C语言练习之猜名次-----A选手说:B第二,我第三;B选手说:我第二,E第四;C选手说:我第一,D第二;D选手说:C最后,我第三;E选手说:我第四,A第一;

      C语言练习之猜名次-----A选手说:B第二,我第三;B选手说:我第二,E第四;C选手说:我第一,D第二;D选手说:C最后,我第三;E选手说:我第四,A第一;

      2025-05-16 09:15:10
      amp , lt , 排名
      2025-05-14 10:02:58

      Linux top 命令使用教程

      Linux top 是一个在Linux和其他类Unix 系统上常用的实时系统监控工具。它提供了一个动态的、交互式的实时视图,显示系统的整体性能信息以及正在运行的进程的相关信息。

      2025-05-14 10:02:58
      CPU , 信息 , 内存 , 占用 , 备注 , 进程
      2025-05-13 09:51:29

      ogg在启动应用进程时报错OGG-00412

      ogg在启动应用进程时报错OGG-00412

      2025-05-13 09:51:29
      ogg , OGG , 时报 , 进程
      2025-05-13 09:51:17

      无法启动ogg配置好的抓取以及投递进程

      无法启动ogg配置好的抓取以及投递进程

      2025-05-13 09:51:17
      ogg , 启动 , 抓取 , 进程
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5253270

      查看更多

      最新文章

      loki仿函数原理

      2025-05-19 09:04:22

      多源BFS问题(1)_01矩阵

      2025-05-16 09:15:17

      BFS解决拓扑排序(1)_课程表

      2025-05-16 09:15:17

      ogg在启动应用进程时报错OGG-00412

      2025-05-13 09:51:29

      46. 全排列,78. 子集,17. 电话号码的字母组合

      2025-05-12 10:19:12

      课程表,实现 Trie (前缀树)

      2025-05-12 10:19:12

      查看更多

      热门文章

      Linux进程间通信

      2023-05-23 09:46:32

      【Linux】ps -ef|grep详解

      2023-05-18 09:34:04

      Linux命令之终止进程kill

      2023-05-26 10:27:33

      特殊权限

      2023-06-25 07:17:17

      Windows关于端口号被占用的问题

      2023-07-19 08:12:05

      win10 下,根据 pid 杀死进程(8080抢占端口)---- java篇

      2023-07-03 08:04:20

      查看更多

      热门标签

      linux java python javascript 数组 前端 docker Linux vue 函数 shell git 节点 容器 示例
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      村里面一共有 n 栋房子 我们希望通过建造水井和铺设管道来为所有房子供水。

      HTML表格、表单标签

      旋转链表

      SQL Server 查询死锁以及解决死锁的基本知识(图文)

      Linux中ps命令使用指南

      K 个一组翻转链表-19. 删除链表的倒数第 N 个结点

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号