当前位置: 首页 > news >正文

Linux 管道

通信的本质

  • 一般而言,进程之间通过OS看到同一份资源,通过OS传递信息

匿名管道

特点

  • 只允许单向通信,主要是为了便于读取
  • 管道文件是一个内存级的文件

基本原理

  • 通过关闭读写fd,实现单向信道
  • 关闭的操作结合 count (文件计数器)

示意图

  1. 磁盘中的文件加载到内存上只有一份内容和属性,这里的内容就是文件缓冲区的形式存储
  2. file对象里只有写的属性和内容的指针

实现

新系统调用pipe

函数原型
#include <unistd.h>int pipe(int pipefd[2]);
输出形参数
  • 整形数组,包含两个文件描述符
    • pipefd[0]:用于读取数据的文件描述符
    • pipefd[1]:用于写入数据的文件描述符

返回值
  • 成功时,pipe 返回 0,并在 pipefd 数组中填充两个文件描述符
  • 失败时,返回 -1,并设置 errno 以指示错误原因

本质:创建出一个内核缓冲区,让fd[1]写进去,df[0]去里面读

注意:不是0号fd和1号fd,而是两个新的fd,用户不同或相同进程之间的通信,

和之前不一样的是,我们虽然创建出两个fd,这两个fd,指向同一个file对象

复习C语言接口perror

函数原型
#include <stdio.h>void perror(const char *s);
参数 
  • s:这是一个自定义的字符串
输出格式
  • <传入的字符串>: <errno 错误描述>
工作原理
  • 当一个系统调用(如 open、read、write)或库函数出错时,通常会返回 -1 或 NULL 并设置 errno。errno 是一个全局整数变量,它保存了错误的代码,指示出错原因。perror 会读取 errno 并根据其值查找相应的错误消息,然后将 s 和错误消息一起打印出来

代码实验过程

#include <iostream>
#include <unistd.h>
#include <cstring>
#include <sys/wait.h>
#include <sys/types.h>using namespace std;
#define MAX 1024
int main()
{int pipefd[2] = {0};if(pipe(pipefd) == -1){perror("pipe");return 1;}int id = fork();if(id < 0){perror("fork");return 1;}// 子进程写if (id == 0){close(pipefd[0]);int cnt = 10;while (cnt){char message[MAX];snprintf(message, sizeof(message), "send message cnt: %d to father", cnt);write(pipefd[1], message, strlen(message));cnt--;sleep(1);}exit(0);}close(pipefd[1]);char receive[MAX]; // 这里需要初始化吗while (true){int n = read(pipefd[0], receive, sizeof(receive) - 1);if (n > 0) //没有我就不写,不然会一直刷新空行{receive[n] = 0;//printf("%s", receive); // 因为没有立即刷新到屏幕上,所以看不到cout << receive << endl;}}waitpid(id, nullptr, 0);return 0;
}
代码目的
  • 子进程写到管道缓冲区里,父进程从管道缓冲区读
  • 实验仅读、仅写、写频率大于读频率、读频率大于写频率4种情况下特点,总结管道特性
情况1:读快于写
代码改动 

  • 红框实现读大于写
  • 蓝框里是代码的细节,就是为了留一个\0,不然cout会出问题
结论
  1.  正常情况:管道里没有数据,读端就会等待,进入睡眠状态,一旦有数据我就读出来
情况2:写快于读
代码改动

实验现象

总结
  •  正常情况:从实验结果里看:管道被写满了,要被读到一定大小才会去写,管道当然有大小
测试管道大小
代码更改

  •  注意32行往里面写的是一个字符a,虽然传的是两个字符,但是最后一个参数锁定了1

发现跑不起来,更改如下:

效果如下 

  • 大小是64KB
ulimit -a

  • 512 bytes是单位,8是个数 ,就是4KB
  • 但是测出来是64KB,具体为什么不清楚
情况3:写端关闭
代码改动

代码效果 

目前不知道-1

结论
  • 写端关闭,只要管道里有数据,读端就可以读取数据,读完后read返回0,表示读到文件结尾
情况4:只写不读
代码改动

注意 
  • 我的代码子进程应该要有一个等待回收的过程,但是没有出现反而是直接被回收了,GPT说这是OS直接调用waitpid给回收了 
结论
  •  关闭读端时,就没法写了,被信号13结束进程了,

总结

4种情况
  1. 正常情况:管道里没有数据,读端就会等待的阻塞状态,进入睡眠状态,一旦有数据就读出来
  2. 正常情况:从实验结果里看:管道被写满了,要被读到一定大小才会去写,管道当然有大小
  3. 写端关闭,只要管道里有数据,读端就可以读取数据,读完后read返回0,表示读到文件结尾
  4. 关闭读端时,就没法写了,被信号13SIGPIPE结束进程了
5种特性
  1. 常用于父子进程之间进程进程间通信
  2. 读写端同步机制
  3. 面向字节流
  4. 管道也是文件,生命周期随进程
  5. 单向通信,半双工通信的一种特殊情况

4种情况都有一个规则:匿名管道的使用是以读为目的,不管你写端是否关闭,你有我就可以读;但是读端关闭,你就不准写了,会终止写端

补充观点

  1. 管道文件和磁盘文件的file对象结构一样,但是指向的方法集一定不一样
  2. 方法集:有一些用于刷新文件缓冲区到磁盘上;
  3. OS一定有办法检测,是否是单向信道

要点

  1. pipe函数的使用
  2. 原理图,通信的本质
  3. 4种情况,5种特性,都指向一种规则
http://www.dtcms.com/a/394624.html

相关文章:

  • NumPy 系列(四):numpy 数组的变形
  • 【Zod 】数据校验新范式:Zod 在 TypeScript 项目中的实战指南
  • 「React实战面试题」useEffect依赖数组的常见陷阱
  • 系统架构设计师部分计算题解析
  • 3.1 BP神经网络结构(反向传播算法)
  • 2026:具身智能软件——开发者工具、范式与方向
  • linux收集离线安装包及依赖包
  • ✅ Python租房数据分析系统 Django+requests爬虫+Echarts可视化 贝壳网全国数据 大数据
  • FREERTOS任务TCB与任务链表的关系-重点
  • C++入门(内含命名空间、IO、缺省参数、函数重载、引用、内联函数、auto关键字、新式范围for循环、关键字nullptr的超全详细讲解!)
  • 红黑树的介绍
  • NumPy 系列(六):numpy 数组函数
  • 手写链路追踪-日志追踪性能分析
  • 数据库自增字段归零(id)从1开始累加
  • 轻量级本地化解决方案:实现填空题识别与答案分离的自动化流程
  • P1104 生日-普及-
  • CMake如何添加.C.H文件
  • 实时数据如何实现同步?一文讲清数据同步方式
  • 六、Java框架
  • 施耐德 M340 M580 数据移动指令 EXTRACT
  • 4. 引用的本质
  • 专业历史知识智能体系统设计与实现
  • 算法基础篇(4)枚举
  • 【C++】二叉搜索树及其模拟实现
  • 第二十一讲:C++异常
  • 2025年9月第2周AI资讯
  • 从 UNet 到 UCTransNet:一次分割项目中 BCE Loss 失效的踩坑记录
  • leetcode刷题记录2(java)
  • JAVA八股文——方法区
  • 链表操作与反转