Linux 进程间通信_匿名管道

news2024/10/28 12:25:49

1.程间通信目的

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

2.匿名管道

1.原理

 上图表示进程打开了一个文件,每一个进程都有一个文件描述符表struct files_struct,

根据文件的路径在磁盘中找到文件的属性和内容,建立文件内核缓冲区 和 文件描述符struct file 里面有指向inode(文件属性)和文件内核缓冲区的指针。然后把文件描述符指针按由小到大的顺序填入文件描述符表的fd_arry[]数组中最后返回下标。

那如果以该进程为父进程创建子进程会是什么样的?

fork()创建一个子进程,肯定会把task_struct struct files_struct这些进程部分复制下来,

struct file不属于进程的一部分,但父子进程需要独立读写文件,也就意味着struct file里面的pos不同pos 通常指的是文件的当前偏移量,即下一个读写操作将从文件的哪个位置开始。),需要子进程复制一份。inode对文件的管理一份就够了,文件内核缓冲区是系统提供的,系统服务每个进程。

那父子进程如何完成通信呢?

父子进程在同一个文件的文件内核缓冲区进行操作,那文件内核缓冲区的内容要不要刷新到磁盘呢?这个文件的作用就是为了让进程间相互通信,没必要保存到磁盘。

有没有一种特殊的文件只用于进程间的通信呢?

管道

父进程读写打开管道,fork()创建子进程。父进程关闭读端,子进程关闭写端。父进程向管道写入数据,子进程可以随时从管道读取数据,而不会干扰彼此的读写操作。形成单向通信.

可以不关读端吗?

建议关,因为管道的设计就是为了单向通信父进程没必要去进行读操作,不关浪费数组资源,文件描述符泄漏。还有可能会进行误操作。

补充:关于重定向 >

./cout.c > test 表示把cout.c文件输出的内容重定向到test文件中。但比不上所有的打印信息都会重定向到test文件中,错误流的信息并不会重定向到test,而是打印到显示器上。

我们知道文件描述符 0输入流 1输出流 2错误流 ,

./cout.c > test 完整的表示是 ./cout.c 1>test 

如果想把错误流也重定向到test文件中

./cout.c &> test 这里的&表示将标准错误与标准输出一起处理。

或者

./cout.c 1>test 2>&1 

>&表示将文件描述符的目标重定向。

2>&1 的意思是将标准错误重定向到标准输出所指向的位置,也就是test文件

2.pipe()系统调用

pipe()系统调用创建一个管道。

#include <unistd.h>

int pipe(int fd[2]);

参数:int fd[2]是一个输出行参数,返回文件描述符,fd[0]以读方式打开管道(读端)

fd[1]以写方式打开管道(写端)

返回值:成功返回0 失败返回-1 error

#include <iostream>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>

int main()
{
    // 1.创建管道
    int fd[2] = {0};
    int n = pipe(fd);
    if (n == -1)
    {
        std::cerr << "pipe error" << std::endl;
        return -1;
    }
    // 2.创建子进程
    pid_t id = fork();
    if (id < 0)
    {
        std::cerr << "fork error" << std::endl;
        return -2;
    }
    if (id == 0)
    {
        int count = 0;
        // 子进程 关闭读端
        close(fd[0]);
        while (1)
        {
            close(fd[0]);
            std::string message = "hello ";
            message += std::to_string(getpid());
            message += ",";
            message += std::to_string(count++);
            // 写入管道
            int n = write(fd[1], message.c_str(), message.size());
            sleep(2);
        }
        exit(0);
    }
    else
    {
        char buff[1024];
        // 父进程 关闭写端
        close(fd[1]);
        // 从管道中读
        while (1)
        {
            int n = read(fd[0], buff, 1024);
            if (n > 0)
            {
                // 读到数据
                buff[n] = '\0'; // 系统字符串没有规定以0结尾
                std::cout << "子进程->父进程 message:" << buff << std::endl;
            }
            else if (n == 0)
            {
                // 写端关闭 读到结尾
                break;
            }
        }
        int status;
        pid_t rid = waitpid(id, &status, 0);
        if (rid == -1)
        {
            std::cerr << "waitpid error" << std::endl;
            return -3;
        }
        //int 16字节 前7位退出信号 后8位退出码
        std::cout<<"子进程pid"<<rid<<"退出码"<<((status<<8)&0xFF)
        <<"退出信号"<<(status&0x7F);
    }
    return 0;
}

上面是子进程写入,父进程读入并输出。

root@hcss-ecs-178e:~/dir1# ./pipe
子进程->父进程 message:hello 8128,0
子进程->父进程 message:hello 8128,1
子进程->父进程 message:hello 8128,2
子进程->父进程 message:hello 8128,3
子进程->父进程 message:hello 8128,4
子进程->父进程 message:hello 8128,5
子进程->父进程 message:hello 8128,6
root@hcss-ecs-178e:~# ps axj|head -1;ps axj|grep pipe
   PPID     PID    PGID     SID TTY        TPGID STAT   UID   TIME COMMAND
   7039    8127    8127    7039 pts/2       8127 S+       0   0:00 ./pipe
   8127    8128    8127    7039 pts/2       8127 S+       0   0:00 ./pipe
   7918    8132    8131    7918 pts/3       8131 S+       0   0:00 grep --color=auto pipe

子进程不断向管道内写入,父进程读入并输出。

3.匿名管道的四种情况

1.管道为空&&管道正常 read会阻塞

子进程写入的速度小于父进程读入的速度,read会阻塞。

2.管道为满&&管道正常 wirte会阻塞

父进程读入速度小于子进程写入的速度,wirte会阻塞。

子进程每次写入一个字符,re表示写入多少字符。

让父进程读入一次就停止,子进程不停写 直到写满管道 wirte阻塞。

65536/1024=64KB 可见管道一次性最大存入64KB数据,父进程读入,子进程才能进行写入。也就意味着父进程读过后的内容在管道内不会保存。

3.管道写端关闭,读端继续。读端读到0,表示读到文件结尾。

 子进程只写入一次

父进程读到0,buff为空,意味着管道为空,读到结尾。退出返回退出码 退出信号

4.写端正常,读端关闭。OS会直接杀死进程

子进程写入管道就是为了让父进程读,如果读端关闭,意味着管道就没有存在的意义,会被系统杀死。

父进程读一次就关闭读端

可以看到退出信号为13,它表示一个进程试图向一个已关闭的管道或套接字写入数据。这种情况下,操作系统会终止该进程,通常会导致进程接收到该信号。

管道的特性

  1. 单向通信管道通常是单向的,数据从一个进程流向另一个进程。可以使用两个管道实现双向通信。

  2. 缓冲区:管道有一个内置的缓冲区,可以暂时存储数据。写入操作不会立即导致读取操作,因此可以在某些情况下实现异步通信。同步互斥

  3. 匿名性:在 Unix 和类 Unix 系统中,匿名管道不具名,不需要在文件系统中创建实体。它们只存在于相关联的进程之间。

  4. 阻塞行为:默认情况下,管道的读写操作是阻塞的。写入端在缓冲区满时会阻塞,读取端在管道为空时会阻塞。这可以帮助协调两个进程的执行。

  5. 进程关系:通常,管道用于父进程与子进程之间的通信。子进程可以继承父进程创建的管道描述符。

  6. 资源释放:当管道的最后一个读取端被关闭时,所有写入该管道的进程都会收到 SIGPIPE 信号,这可能导致它们终止。生命周期随进程

  7. 大小限制:管道的缓冲区大小通常受到操作系统的限制,不同系统的大小可能不同。

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

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

相关文章

Linux CentOS7下创建SFTP服务器

本文详细介绍了在Linux CentOS上部署安全文件传输协议&#xff08;SFTP&#xff09;服务器的全过程。SFTP基于SSH&#xff08;安全壳层协议&#xff09;提供文件传输服务&#xff0c;继承了SSH的安全特性&#xff0c;如数据加密、完整性验证和服务器认证等&#xff0c;确保数据…

信号与系统学习:周期信号的频谱

一、概念 1. 什么是频谱&#xff1f; 频谱描述了信号在不同频率上的能量分布对于一个周期信号&#xff0c;其频谱通常是离散的&#xff0c;由一系列离散的频率成分组成 2. 周期信号与傅里叶级数 周期信号可以用傅里叶级数展开&#xff0c;表示为无数个正弦和余弦&#xff0…

巡飞单机多旋翼无人机技术详解

巡飞单机多旋翼无人机技术是一种集成了多种先进技术的无人机系统&#xff0c;它具备自主飞行、长续航、高精度控制以及多任务负载能力等特点。以下是对巡飞单机多旋翼无人机技术的详细解析&#xff1a; 一、机架与结构设计 1.材料选择&#xff1a;为了确保无人机能够承载足够…

基于深度学习的图像修复系统设计与实现(PyQt5、CodeFormer ffhq-dataset数据集)

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

logback日志导入使用

1导入配置 <!-- 日志 &#xff0c; 会自动传递slf4j门面--> <dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version> </dependency>2 引入配置 Logback要求…

Synergy遇见的问题

1.两台设备无法ping通 首先两个设备是在同一个局域网中&#xff0c;但任然是无法ping通 问题所在&#xff1a;防火墙进行了隔离&#xff1b; 解决方法&#xff1a; &#xff08;1&#xff09;关闭防火墙 没有用过&#xff0c;个人感觉不怎么安全就没有使用&#xff1b; &am…

react18中的受控与非受控组件及ref的使用

受控与非受控组件 受控组件,基于修改 state 的值,修改组件内部的状态&#xff0c;来实现页面的更新&#xff0c;推荐使用 非受控组件&#xff0c;基于 ref 获取 dom 的值&#xff0c;来实现页面的更新,不推荐使用,偶尔特殊的场景会使用 给需要获取的元素设置 ref“xxx”,后期基…

一步一步从微信小程序获取asp.net Core API的数据

前面我们说过&#xff0c;如何使用微信小程序获取asp.net的数据&#xff0c;这里我们继续介绍如何获取asp.net core api的数据。两者之间还是有一些差别的。本篇博文旨在详细介绍如何一步一步从微信小程序获取asp.net Core API的数据。 文章目录 一、建立并了解asp.net core we…

Git 创建SSH秘钥

1、命令行输入 ssh-keygen -t rsa -b 4096 2、系统提示你“Enter a file in which to save the key”&#xff0c;直接按回车键 3、再提示你输入密码的时候直接按回车键&#xff0c;创建没有密码的SSH密钥 4、密钥对创建后&#xff0c;可以在自己电脑对应的 ~/.ssh 目录下找到…

vue 果蔬识别系统百度AI识别vue+springboot java开发、elementui+ echarts+ vant开发

编号&#xff1a;R03-果蔬识别系统 简介&#xff1a;vuespringboot百度AI实现的果蔬识别系统 版本&#xff1a;2025版 视频介绍&#xff1a; vuespringboot百度AI实现的果蔬识别系统前后端java开发&#xff0c;百度识别&#xff0c;带H5移动端&#xff0c;mysql数据库可视化 1 …

Unity编辑器制作多级下拉菜单

Unity编辑器下拉菜单 大家好&#xff0c;我是阿赵。   在Unity引擎里面编写工具插件&#xff0c;有时候会用到一些特殊的菜单形式&#xff0c;比如下拉选项。 通过下拉菜单&#xff0c;给用户选择不同的选项。   如果只是一层的下拉列表&#xff0c;可以用EditorGUILayout.…

西南大学软件专硕考研难度分析!

C哥专业提供——计软考研院校选择分析专业课备考指南规划 西南大学软件工程学硕近三年呈现出招生规模稳定、复试线稳中有升的特点。2024届实际录取8人&#xff0c;复试分数线305分&#xff0c;复试录取率67%&#xff0c;相比去年复试线略有下降但仍高于2022届&#xff0c;显示出…

Maven 项目构建打包,如何引入本地 Jar 包?

上一篇讲到 Maven 离线仓库的使用&#xff0c;反响不错很多人收藏&#xff0c;这一篇还是继续聊 Maven 。假如你发现某开源项目有个 bug 影响到自己的系统&#xff0c;但官方还没修复&#xff0c;自己定位到了本地修改打了包先应急用&#xff0c;那么如何在其他项目上使用该包&…

【动态规划】力扣198.打家劫舍

目录 一、题目二、思路1.递归2.递推 三、代码 一、题目 二、思路 1.递归 题目中指出不可以选相邻的房间&#xff0c;说明如果选了第 1 间&#xff0c;那么第 2 间一定不可以选&#xff0c;第 3 间房间可以选&#xff0c;也可以不选……假设是按照从第 1 间房间开始依次往后选…

【测试】——Fiddler入门

&#x1f4d6; 前言&#xff1a;本文介绍Fiddler&#xff0c;一个强大的HTTP协议调试代理工具。文章详细讲解了Fiddler的安装步骤、基础操作、抓包技巧以及模拟测试等内容。 目录 &#x1f552; 1. Fiddler基础介绍&#x1f558; 1.1 安装&#x1f558; 1.2 基础操作&#x1f5…

[oeasy]python038_ range函数_大小写字母的起止范围_start_stop

range函数_大小写字母的起止范围_start_stop 回忆上次内容 所有字符 都有序号 就连 空格 也不例外 空格 序号32是 print函数中 sep参数的 默认值 字符 在计算机中 用数字序号 来 存储表示 字符序号 有规律 a 对应 97b 对应 98c 对应 99 连续字母 对应 连续序号 似乎应该是 天经…

SOLID - 接口隔离原则(Interface Segregation Principle)

SOLID - 接口隔离原则&#xff08;Interface Segregation Principle) 定义 接口隔离原则&#xff08;Interface Segregation Principle&#xff0c;ISP&#xff09;是面向对象设计中的五个基本原则之一&#xff0c;通常缩写为SOLID中的I。这一原则由Robert C. Martin提出&…

校园气膜体育馆:学生锻炼与成长的新空间—轻空间

在现代教育中&#xff0c;学生的身心健康日益受到重视&#xff0c;校园体育设施的建设成为学校发展的重要一环。为更好地满足学生在节假日锻炼与学习的需求&#xff0c;校园气膜体育馆应运而生&#xff0c;成为校园内一处崭新的活力空间。 打破场地限制&#xff0c;打造优质运动…

LeetCode 热题 100之矩阵

1.矩阵置0 思路分析&#xff1a;使用标记数组 记录需要置为 0 的行和列&#xff1a;使用两个布尔数组 zeroRows 和 zeroCols 来记录需要置为 0 的行和列两次遍历 第一遍遍历整个矩阵&#xff0c;找到所有为0的元素&#xff0c;并更新zeroRows和zeroCols&#xff1b;第二遍遍历…

快速入门HTML

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗 如有错误&#xff0c;欢迎指出~ 目录 第一个html文件 标签 h1~h6 p >段落标签 br > 换行标签 img >图片标签 a >超链接标签 表格标签 表单标签 表单控件 form表单 ⽆语义标签:div&span 综…