Linux应用开发(8):Linux进程间通信(IPC):管道

embedded/2024/9/22 19:43:22/

Linux应用开发(7):Linux进程间通信(IPC):POSIX消息队列icon-default.png?t=N7T8https://blog.csdn.net/tecsai/article/details/137879465

1. 简述

        我们在前面已经介绍了进程间通信(IPC)常用的“消息队列”。本节将讲解另外一种常用的IPC机制,我们称作管道

        管道可以理解为一种特殊的文件,也可以理解为一种特殊的缓冲区,它允许两个进程通过一个半双工的通道进行数据通信。

2. 基本概念

        上面提到,管道是半双工的,数据只能向一个方向流动。在使用过程中,需要双方同时打开(也可以由父进程先打开,再由子进程继承)。管道分为无名管道和命名管道。

无名管道

        无名管道只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程),它之所以成为无名管道,是因为它们不需要文件系统中的文件支持。管道的缓冲区是有限的。

命名管道

        相对于无名管道,命名管道是基于特殊的文件来进行通信的。在使用时,首先需要文件系统中有一个路径和名称,因此命名管道是可以允许不相关的进程进行通信。

3. 无名管道

        无名管道顾名思义,是没有被命名的管道,其存在于内存中,仅允许相关的两个进程间进行通信。

PS:可以联想到无名信号量和有名信号量,前者在内存中,仅允许关联进程同步,后者则可以在不相关联的进程间进行同步。

        无名管道的创建采用如下API。

#include <unistd.h>

int pipe(int fd[2]);

        fd 是一个整型数组,包含两个元素:fd[0] 用于读取,fd[1] 用于写入。

        无名管道例程。

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/wait.h>int main(int argc, char* argv[]){int fds[2];pid_t pid;char buffer[50];if (pipe(fds) == -1) {perror("pipe");exit(EXIT_FAILURE);}/** 创建进程. */pid = fork();if (pid == -1) {perror("fork");exit(EXIT_FAILURE);}if (pid == 0) {/** 子进程:写入管道. */close(fds[0]); ///< 关闭读端write(fds[1], "Hello, Parent!", 15);close(fds[1]); ///< 写入后关闭写端} else {/** 父进程:读取管道。 */wait(NULL); ///< 等待子进程结束close(fds[1]); ///< 关闭写端read(fds[0], buffer, 50);close(fds[0]); ///< 读取后关闭读端printf("Parent Process: %s\n", buffer);}return 0;}

4. 命名管道

        命名管道(FIFO)是一种特殊的文件,它允许不相关的进程通过一个命名的路径进行通信。与无名管道不同,命名管道在文件系统中有一个路径和名称。

        创建命名管道的API如下。

#include <sys/stat.h>

int mkfifo(const char *path, mode_t mode);

命名管道例程。

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <sys/stat.h>int main(int argc, char* argv[]){/** 文件路径. */const char *fifo_name = "my_fifo";int fd;/** 创建命名管道. */if (mkfifo(fifo_name, 0666) == -1) {perror("mkfifo");exit(EXIT_FAILURE);}/** 打开命名管道进行写入. */fd = open(fifo_name, O_WRONLY);if (fd == -1) {perror("open");exit(EXIT_FAILURE);}/** 写入命名管道. */write(fd, "Hello, through FIFO!", 20);close(fd);/** 清理命名管道. */unlink(fifo_name);return 0;}

5. 什么时候选择使用管道

父子进程通信:在C++程序中,你可能需要创建子进程来执行特定的任务。管道可以用来在父进程和子进程之间安全地交换数据。

进程生成和过滤:如果你的应用程序需要生成大量的数据,并且这些数据需要被另一个进程即时处理或过滤,管道可以有效地连接生成器和消费者。

并行处理:在需要并行处理任务时,可以通过管道将任务的输出传递给其他进程,这些进程可以并行地处理数据。

后台任务处理:当你需要在后台运行一个任务,并且不希望阻塞主进程时,可以使用管道来与后台任务通信。

日志记录:管道可以用于实现日志系统,其中一个进程负责记录日志信息,而另一个进程负责监控和处理这些日志。

信号传递:在多进程程序中,管道可以用来传递信号,如通知其他进程某个事件已经发生。

资源共享:当多个进程需要访问同一个资源,但又需要协调访问以避免冲突时,可以使用管道来控制对资源的访问。

简化线程使用:在某些情况下,使用管道进行进程间通信比使用线程更简单,尤其是在涉及复杂同步和锁管理的场景中。

跨平台兼容性:如果你的C++应用程序需要在不同的操作系统上运行,使用管道可以提高代码的可移植性。

模块化设计:在构建模块化的C++应用程序时,管道可以帮助你将不同的功能模块化为独立的进程,并通过管道进行通信。


http://www.ppmy.cn/embedded/7042.html

相关文章

微服务分布式缓存:无法反序列化 Cannot deserialize;

问题描述 在拆分SpringBoot项目搭建微服务的过程中&#xff0c;需要配置分布式缓存&#xff0c;对redis进行配置&#xff0c;配置完成后&#xff0c;在启动Knife4j文档界面时报错&#xff0c;发现是redis无法反序列化的问题&#xff0c;但是报错中所指出的类com.jhin.jhinoj.m…

GO环境及入门案例

文章目录 简介一、win GO开发环境安装二、Linux go运行环境二、GO代码入门2.1 导包案例2.2 赋值2.3 变量、函数2.4 三方库使用 简介 go不是面向对象语言&#xff0c; 其指针、结构体等比较像C&#xff0c;知名的go 开源项目有docker k8s prometheus node-exporter等 一、win …

百度文心一言与谷歌Gemini的对比

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 本文从多角度将百度文心一言与谷歌Gemini进行对比。因为不同评测基准的侧重点和难度可能有所不同&#xff0c;所以本文涉及到的评测结果仅供参考。Gemini和文心一言都是非常…

sqlite

SQLite是一种轻量级的嵌入式数据库引擎&#xff0c;它被广泛应用于移动设备、嵌入式系统和桌面应用程序等领域。最近&#xff0c;SQLite在以下几个方向上有了新的发展&#xff1a; 1. 支持JSON数据类型&#xff1a;SQLite 3.9版本引入了对JSON数据类型的支持&#xff0c;使得开…

装饰器学习

【一】什么是装饰器 装饰器指的就是为被装饰的对象添加新的功能 器 代表工具 增加后的调用方式不变 在不改变源代码和调用方式的基础上增加额外的新功能 【二】装饰器的用途 对上线后的程序进行新功能的增加和修改 给一个功能增加新的需求或者改变原来的程序运行逻辑 【…

【Linux】应用层协议:HTTP

URL 在之前的文章中我们实现了一个网络版本的计算器&#xff0c;在那个计算器中揉合了协议定制以及序列化反序列化的内容&#xff0c;我们当时也自己定制了一套协议标准&#xff0c;比如请求和响应的格式应该是什么&#xff1f;如何读到一个完整的报文&#xff1f;支持的运算符…

Flask 解决指定端口无法生效问题

问题重现 手动指定的IP端口是app.run(host0.0.0.0, port9304)&#xff0c;但是启动的地址显示的却是http://127.0.0.1:5000。 if __name__ __main__:app.run(host0.0.0.0, port9304)启动地址如下&#xff1a; 解决方案 PyCharm会自动识别出来flask项目&#xff08;即使你…

Spring AOP的实现方式与原理

目录 认识IOC与AOP AOP的实现方式 Aspect注解实现AOP 自定义注解实现AOP Spring AOP原理 代理模式 静态代理和动态代理 JDK动态代理 CGLIB动态代理 Spring AOP实现的哪种代理 认识IOC与AOP IOC又称为控制反转,也就是控制权发生了反转.在传统的程序中,我们是需要自己…