Linux——进程通信(一) 匿名管道

news2024/12/24 3:45:39

目录

前言

一、进程间通信

二、匿名管道的概念

三、匿名管道的代码实现

四、管道的四种情况

1.管道无数据,读端需等待

2.管道被写满,写端需等待

3.写端关闭,读端一直读取

4.读端关闭,写端一直写入

五、管道的特性


前言

之前我们学习的进程,都是进程自己干自己的事情,最多就父进程等待一下子进程,两个进程自己完成自己的任务,并没有太多关系,虽说进程具有独立性,但进程并不孤僻,进程之间交流是可以完成的,今天我们就来学习进程通过匿名管道进行通信,匿名管道并不难,不要被它名字唬住了。

一、进程间通信

进程间通信的目的如下 

  • 数据传输:一个进程需要将它的数据发送给另一个进程
  • 资源共享:多个进程之间共享同样的资源。
  • 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止 时要通知父进程)。
  • 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另 一个进程的所有陷入和异常,并能够及时知道它的状态改变。

要实现这些目的的前提,就是进程间可以通信起来。但是我们知道进程具有独立性,如果数据传输通过数据拷贝的方式进行,也就是将A进程的数据直接拷贝给B进程,这样就破坏了进程的独立性。这时就需要一个AB进程都能去到的地方,往这个共享区进行读写,这样就能保证进程独立性的同时,还实现了通信的功能,操作系统就很适合当这个中间人

进程间通信的本质:让不同的进程看到同一份资源

进程间通信分类分为管道、System V进程间通信、POSIX进程间通信。今天我们着重学习管道中的匿名管道

二、匿名管道的概念

        首先,我们知道一个进程有他的task_struct,这里面有一个指向文件结构体的指针,该文件结构体里面存在文件标识符数组,数组0号下标指向键盘(stdin),1指向显示器(stdout),2指向显示器(stderr)。

        现在,我新打开一个文件,那么该文件的文件标识符就为3,此时我fork创建子进程,子进程要继承父亲的task_struct、虚拟地址空间、页表等等,都继承了task_struct了,那么files_struct也要继承一份(因为如果共用files_struct,那么子进程想打开新的文件,肯定会往文件标识符数组里面写内容,那么父进程也会看见,这岂不是破坏了进程的独立性)。

        既然files_struct也继承了,里面指向的新文件也肯定继承了,文件有文件缓冲区,如果我父进程往该文件进行写入,子进程对文件进行读取,这样是不是就完成了进程间的通信。(注意:虽然文件缓冲区一般情况是要刷新到磁盘中的,但是这里文件只充当了管道的作用,刷新到磁盘再读取磁盘的效率非常低,因此这里并不会涉及到磁盘,只是内存级别的数据拷贝)

但是这里还存在一点小问题,就是父进程如果只是只读方式打开文件,那么子进程也是只读的方式打开文件,并不能写入,因此需要父进程同时对一个文件进行打开读取和打开写入操作,子进程继承下来后,既可以读取又可以写入,那么到时候,我想让子进程写,父进程读,就只需关闭子进程读,父进程写就可以了,反之亦然。

我们对同一文件进行读和写,在内核数据结构中实际上会生成两个struct file,只不过这两个struct file,都指向的是同一个inode,同一个缓冲区。进程关闭文件时,将文教标识符数组清空,file里面的引用计数 -- ,进程就不管文件了,但操作系统还得判断当前文件引用计数是否为0,为0证明没有进程还在使用该文件,就可以关闭,不为0就不会真正的关闭。

这就是管道名字的由来,只支持一边读,另一边写,是半双工的一种特殊方式。 同时这个管道我们并不关心它的名字,因此叫做匿名管道。

管道是Unix中最古老的进程间通信的形式。

在linux命令中,|  就是管道,可以将输出的信息读取给后面的命令处理。

三、匿名管道的代码实现

由于管道接口是不需要将数据刷新到外设,因此接口需要特殊设计。

#include 功能:创建一无名管道

原型         int pipe(int fd[2]);

参数         fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端

返回值:成功返回0,失败返回错误代码

我们直接上代码,利用pipe创建管道,子进程去写数据,父进程来读数据 

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <cstring>
#include <cassert>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;

#define MAX 1024
int main()
{
    // 建立管道
    int pipefd[2] = {0};
    int n = pipe(pipefd);
    assert(n==0);   //release模式不会执行

    pid_t id = fork();
    if (id < 0)
    {
        perror("fork");
        return 1;
    }
    // 子写 父读
    if (id == 0)
    {
        // child
        close(pipefd[0]);
        char message[MAX];
        int cnt = 10;
        while(cnt)
        {
            snprintf(message, MAX, "hello father,I am child,pid: %d,cnt: %d ", getpid(),cnt);
            write(pipefd[1],message,strlen(message));
            cnt--;
            sleep(1);
        }
        exit(0);
    }

    // 父进程
    close(pipefd[1]);
    char buff[MAX];
    while (true)
    {
        ssize_t n = read(pipefd[0], buff, MAX - 1);
        if (n > 0)
        {
            buff[n] = '\0';
            cout << getpid()<<", child say:" << buff << "to me!" << endl;
        }
    }
    pid_t rid = waitpid(id, NULL, 0);
    if (rid = id)
    {
        cout << "wait success" << endl;
    }
    return 0;
}

成功进行数据通信

四、管道的四种情况

1.管道无数据,读端需等待

如果管道中没有数据了,读端需要等待,直到写段写入数据。

我们让子进程休眠100秒

 发现父子进程都在休眠,印证了管道中没有数据,读端并不会一直运行。

2.管道被写满,写端需等待

管道被写满了,写端需要等待,等读端读走数据才可以继续写。

我们让写端死循环写入,读端进行休眠。

发现写端写到一定数据后不动了。 他需要等待读端读取数据再写入。

3.写端关闭,读端一直读取

我们关闭写端,读端一直读取,读端会读到read返回值为0,表示文件结尾。

以下是写端休眠100秒,一直不写,读端读数据,看n返回多少,都会打印。

 程序没有结果,这也印证了上面的情况,写端不写入,读端需等待,read不会返回值。

后面让读端关闭,查看写端打印结果 

写端关闭了,因此可以返回值,n == 0,表示读到文件末尾。

4.读端关闭,写端一直写入

读端关闭,写端一直写入,操作系统会发送 SIGPIPE 直接杀掉写端进程。

退出码为13。

发送了13号  SIIGPIPE

五、管道的特性

  1. 匿名管道,允许有血缘关系的进程通信
  2. 匿名管道,默认读写段要提供同步机制
  3. 面向字节流
  4. 管道的声明周期随进程(进程死亡,文件自然close,管道也不存在了)
  5. 管道式单向通信的,半双工通信的一种特殊情况。

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1525275.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

功能测试--APP性能测试

功能测试--APP性能测试 内存数据查看内存测试 CPU数据查看CPU测试 流量和电量的消耗流量测试流量优化方法电量测试电量测试场景&#xff08;大&#xff09; 获取启动时间启动测试--安卓 流畅度流畅度测试 稳定性稳定性测试 内存数据查看 内存泄露:内存的曲线持续增长(增的远比减…

【vscode】vscode重命名变量后多了很多空白行

这种情况&#xff0c;一般出现在重新安装 vscode 后出现。 原因大概率是语言服务器没设置好或设置对。 以 Python 为例&#xff0c;到设置里搜索 "python.languageServer"&#xff0c;将 Python 的语言服务器设置为 Pylance 即可。

机器学习-绪论

机器学习致力于研究如何通过计算的手段、利用经验来改善系统自身的性能。在计算机系统中&#xff0c;“经验”通常以“数据”的形式存在&#xff0c;因此&#xff0c;机器学习所研究的主要内容&#xff0c;是关于在计算机上从数据中产生“模型”的算法&#xff0c;即“学习算法…

语音控制模块_雷龙发展

一 硬件原理 1&#xff0c;串口 uart串口控制模式&#xff0c;即异步传送收发器&#xff0c;通过其完成语音控制。 发送uart将来自cpu等控制设备的并行数据转换为串行形式&#xff0c;并将其串行发送到接收uart&#xff0c;接收uart然后将串行数据转换为接收数据接收设备的并行…

【MATLAB源码-第162期】基于matlab的MIMO系统的MMSE检测,软判决和硬判决误码率曲线对比。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 MIMO系统(Multiple-Input Multiple-Output&#xff0c;多输入多输出系统)是现代无线通信技术中的关键技术之一&#xff0c;它能够显著增加通信系统的容量和频谱效率&#xff0c;而不需要增加额外的带宽或发射功率。在MIMO系统…

PostgreSQL-管理-2.3-Spring项目开发对接

1 Spring Boot中如何使用 在安装好了PostgreSQL之后,下面我们尝试一下在Spring Boot中使用PostgreSQL数据库。 1.1 配置数据库连接 1、在pom.xml中引入访问PostgreSQL需要的两个重要依赖: <dependency><groupId>org.springframework.boot</groupId><…

VSCode+python单步调试库代码

VSCodepython单步调试库代码 随着VSCode版本迭代更新&#xff0c;在最新的1.87.x中&#xff0c;使用Python Debugger扩展进行调试时&#xff0c;扩展的justMyCode默认属性为true&#xff0c;不会进入库中的代码。这对debug而言不太方便&#xff0c;因此需要手动设置一下&#…

Docker 镜像源配置

目录 一、 Docker 镜像源1.1 加速域名1.2 阿里云镜像源&#xff08;推荐&#xff09; 二、Docker 镜像源配置2.1 修改配置文件2.1.1 Docker Desktop 配置2.1.2 命令行配置 2.2 重启 Docker 服务2.2.1 Docker Desktop 重启2.2.2 命令行重启 2.3 检查是否配置成功 参考资料 一、 …

windows 安装cuda 11.2过程记录

参考&#xff1a; https://blog.csdn.net/m0_45447650/article/details/123704930 https://zhuanlan.zhihu.com/p/99880204?from_voters_pagetrue 在显卡驱动被正确安装的前提下&#xff0c;在命令行里输入nvidia-smi.exe 下载CUDA Toolkit: https://developer.nvidia.com/…

SpringBoot实现邮件发送

一.准备 引入starter <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId> </dependency>二.邮件发送需要的配置 因为各大邮件都有其对应安全系统&#xff0c;不是项目中想用就…

【数据结构与算法】(13):冒泡排序和快速排序

&#x1f921;博客主页&#xff1a;Code_文晓 &#x1f970;本文专栏&#xff1a;数据结构与算法 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多数据结构与算法点击专栏链接查看&…

深度序列模型与自然语言处理:基于TensorFlow2实践

目录 写在前面 推荐图书 编辑推荐 内容简介 作者简介 推荐理由 写在最后 写在前面 本期博主给大家推荐一本深度学习的好书&#xff0c;对Python深度学习感兴趣的小伙伴快来看看吧&#xff01; 推荐图书 《深度序列模型与自然语言处理 基于TensorFlow2实践》 直达链接…

数据结构——串,数组和广义表详解

目录 1.串的定义 1.串的几个术语 2.案例引入 3.串的类型定义&#xff0c;存储结构及运算 1.串的顺序存储结构 代码示例&#xff1a; 2.串的链式存储结构 代码示例&#xff1a; 3.串的模式匹配算法 1.BF算法 1.BF算法设计思想 2.BF算法描述 代码示例&…

Github 2024-03-18开源项目日报Top10

根据Github Trendings的统计,今日(2024-03-18统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目7TypeScript项目3非开发语言项目1Solidity项目1《Hello 算法》:动画图解、一键运行的数据结构与算法教程 创建周期:476 天协议类型…

数据分析 | NumPy

NumPy&#xff0c;全称是 Numerical Python&#xff0c;它是目前 Python 数值计算中最重要的基础模块。NumPy 是针对多维数组的一个科学计算模块&#xff0c;这个模块封装了很多数组类型的常用操作。 使用numpy来创建数组 import numpy as npdata np.array([1, 2, 3]) print…

二叉搜索树、B-树、B+树

二叉搜索树 二叉查找树&#xff0c;也称为二叉搜索树、有序二叉树或排序二叉树&#xff0c;是指一棵空树或者具有下列性质的二叉树&#xff1a; 若任意节点的左子树不空&#xff0c;则左子树上所有节点的值均小于它的根节点的值&#xff1b;若任意节点的右子树不空&#xff0…

【C++】手撕红黑树

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;能直接手撕红黑树。 > 毒鸡汤&#xff1a;行到…

HTML5、CSS3面试题(二)

上一章:HTML5、CSS3面试题&#xff08;一&#xff09; 哪些是块级元素那些是行内元素&#xff0c;各有什么特点 &#xff1f;&#xff08;必会&#xff09; 行内元素: a、span、b、img、strong、input、select、lable、em、button、textarea 、selecting 块级元素&#xff1…

VSCode + PicGo + Github 实现markdown图床管理

目录 PicGo客户端VSvode插件 PicGo客户端 PicGo 是一个图片上传管理工具 官网&#xff1a;https://molunerfinn.com/PicGo/ github图传使用说明&#xff1a;https://picgo.github.io/PicGo-Doc/zh/guide/config.html#GitHub图床 步骤&#xff1a; 1、创建一个github公开仓库…

Mac玩《幻兽帕鲁》为什么打不开D3DMetal?d3d错误怎么办 d3dxl error

我之前发了一篇讲Mac电脑玩Steam热门新游《幻兽帕鲁》的文章&#xff08;没看过的点这里&#xff09;&#xff0c;后来也看到很多朋友去尝试了&#xff0c;遇到了一些问题&#xff0c;无法进入《幻兽帕鲁》游戏&#xff0c;或者是玩的时候卡顿以及出现黑屏&#xff0c;通过我的…