使用Linux命名管道(FIFO)实现无血缘关系进程间通信

使用Linux命名管道(FIFO)实现无血缘关系进程间通信

使用Linux命名管道实现无血缘关系进程间通信

1. 引言

在Linux系统中,进程间通信(IPC)是编程中常见的需求。传统上,有血缘关系的进程(如父子进程)可以通过管道进行通信,但无血缘关系的进程则需要其他IPC机制。本文将介绍如何使用Linux命名管道(FIFO)实现无血缘关系进程间的通信,展示其原理、实现方法和实际应用场景。

2. 命名管道(FIFO)概述

命名管道(FIFO, First In First Out)是一种特殊的文件类型,它允许不相关的进程之间进行通信。与匿名管道不同,命名管道不要求通信的进程之间有血缘关系,因此可以用于任意两个进程之间的通信。

命名管道的主要特点包括:

  1. 命名管道存在于文件系统中,可以通过路径名访问
  2. 命名管道是单向的,数据只能在一个方向上流动
  3. 命名管道不要求通信的进程之间有血缘关系
  4. 命名管道在内核中维护,不占用磁盘空间
  5. 当所有进程关闭了命名管道的文件描述符时,命名管道的内容会被销毁

3. 创建和使用命名管道

3.1 使用命令行创建命名管道

可以使用mkfifo命令在命令行中创建命名管道:

mkfifo my_pipe 

这将在当前目录下创建一个名为my_pipe的命名管道文件。

3.2 使用C语言创建命名管道

在C语言中,可以使用mkfifo函数来创建命名管道:

#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<stdio.h>#include<stdlib.h>intmain(){constchar*fifo_path ="/tmp/my_fifo";// 创建命名管道if(mkfifo(fifo_path,0666)==-1){perror("mkfifo");exit(EXIT_FAILURE);}printf("Named pipe created: %s\n", fifo_path);return0;}

4. 实现无血缘关系进程间通信

4.1 写进程示例

下面是一个写进程的示例代码,它向命名管道写入数据:

#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<fcntl.h>#include<string.h>intmain(){constchar*fifo_path ="/tmp/my_fifo";constchar*message ="Hello from writer process!";// 以只写方式打开命名管道int fd =open(fifo_path, O_WRONLY);if(fd ==-1){perror("open");exit(EXIT_FAILURE);}// 向命名管道写入数据write(fd, message,strlen(message));printf("Message sent: %s\n", message);// 关闭命名管道close(fd);return0;}

4.2 读进程示例

下面是一个读进程的示例代码,它从命名管道读取数据:

#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<fcntl.h>#include<string.h>#defineBUFFER_SIZE256intmain(){constchar*fifo_path ="/tmp/my_fifo";char buffer[BUFFER_SIZE];// 以只读方式打开命名管道int fd =open(fifo_path, O_RDONLY);if(fd ==-1){perror("open");exit(EXIT_FAILURE);}// 从命名管道读取数据int bytes_read =read(fd, buffer, BUFFER_SIZE -1);if(bytes_read ==-1){perror("read");exit(EXIT_FAILURE);} buffer[bytes_read]='\0';// 确保字符串以null结尾printf("Message received: %s\n", buffer);// 关闭命名管道close(fd);return0;}

4.3 运行示例

要运行这个示例,首先需要创建命名管道,然后分别编译和运行写进程和读进程。需要注意的是,读进程应该先于写进程启动,因为读进程在打开命名管道时会阻塞,直到有另一个进程以写方式打开同一个命名管道。

# 创建命名管道mkfifo /tmp/my_fifo # 编写进程 gcc writer.c -o writer ./writer &# 读进程 gcc reader.c -o reader ./reader 

5. 命名管道的高级特性

5.1 非阻塞打开命名管道

默认情况下,以只读或只写方式打开命名管道会导致进程阻塞,直到有另一个进程以相反的方式打开同一个命名管道。为了避免阻塞,可以在打开命名管道时指定O_NONBLOCK标志:

// 非阻塞方式打开命名管道int fd =open(fifo_path, O_RDONLY | O_NONBLOCK);

5.2 使用select或poll监控命名管道

可以使用selectpoll函数来监控命名管道的可读性或可写性,从而避免阻塞:

#include<sys/select.h>#include<poll.h>// 使用select监控命名管道 fd_set read_fds;structtimeval timeout;FD_ZERO(&read_fds);FD_SET(fd,&read_fds); timeout.tv_sec =5;// 5秒超时 timeout.tv_usec =0;int ret =select(fd +1,&read_fds,NULL,NULL,&timeout);if(ret >0){if(FD_ISSET(fd,&read_fds)){// 命名管道可读// 执行读取操作}}// 使用poll监控命名管道structpollfd fds; fds.fd = fd; fds.events = POLLIN;// 监控可读事件int ret =poll(&fds,1,5000);// 5秒超时if(ret >0){if(fds.revents & POLLIN){// 命名管道可读// 执行读取操作}}

6. 命名管道的注意事项

  1. 单向通信:命名管道是单向的,如果需要双向通信,需要创建两个命名管道。
  2. 阻塞行为:默认情况下,打开命名管道会导致进程阻塞,直到有另一个进程以相反的方式打开同一个命名管道。
  3. 数据完整性:写入命名管道的数据可能会被截断,特别是在写入大量数据时。因此,需要确保数据的完整性。
  4. 错误处理:在使用命名管道时,需要正确处理各种错误情况,如管道不存在、权限不足等。
  5. 资源清理:使用完命名管道后,应该关闭文件描述符,并在不需要时删除命名管道文件。

7. 实际应用场景

命名管道在实际开发中有多种应用场景,例如:

  1. 日志收集系统:多个不同的应用程序可以将日志写入同一个命名管道,而日志收集进程则从该管道读取日志。
  2. 服务间通信:在微服务架构中,可以使用命名管道作为轻量级的进程间通信机制。
  3. 命令行工具:命令行工具可以使用命名管道接收来自其他程序的输入或发送输出到其他程序。
  4. 测试框架:在测试过程中,可以使用命名管道模拟不同组件之间的交互。

8. 总结

本文介绍了Linux命名管道(FIFO)的基本概念、创建方法以及如何使用它来实现无血缘关系进程间的通信。通过示例代码,展示了如何创建命名管道、打开和关闭命名管道,以及如何使用命名管道进行进程间通信。此外,还介绍了命名管道的高级特性和注意事项。

命名管道是一种简单而有效的进程间通信机制,特别适用于不相关的进程之间的通信。通过合理使用命名管道,可以实现进程间的数据交换和同步,提高程序的灵活性和可扩展性。

Read more

Python操作国产金仓数据库(KingbaseES)全流程:搭建自己的网页数据管理(增删改查)

Python操作国产金仓数据库(KingbaseES)全流程:搭建自己的网页数据管理(增删改查)

Python操作国产金仓数据库(KingbaseES)全流程:搭建自己的网页数据管理(增删改查) Python操作国产金仓数据库(KingbaseES)全流程:搭建自己的网页数据管理(增删改查),现在国产化替代是大趋势,国产数据库的应用越来越广,金仓数据库(KingbaseES)作为其中的佼佼者,在政务、金融这些领域用得特别多。今天我就带大家从0到1,一步步实现用Python操作KingbaseES数据库,还会基于Flask框架搭一个可视化的网页管理系统,数据的增删改查全流程都能搞定,不管你是Python开发者还是数据库管理员,跟着学都能用得上。 前言     中电科金仓(北京)科技股份有限公司(以下简称“电科金仓”)成立于1999年,是成立最早的拥有自主知识产权的国产数据库企业,也是中国电子科技集团(CETC)成员企业。电科金仓以“提供卓越的数据库产品助力企业级应用高质量发展”为使命,致力于“成为世界卓越的数据库产品与服务提供商”。     电科金仓自成立起始终坚持自主创新,专注数据库领域二十余载,具备出色的数据库产品研发及服务能力,核心产品金仓数据库管理系统Kingbas

By Ne0inhk
C++ 拷贝构造函数与赋值运算符:深拷贝与浅拷贝的核心辨析

C++ 拷贝构造函数与赋值运算符:深拷贝与浅拷贝的核心辨析

C++ 拷贝构造函数与赋值运算符:深拷贝与浅拷贝的核心辨析 💡 学习目标:掌握拷贝构造函数与赋值运算符的定义及调用场景,理解深拷贝与浅拷贝的本质区别,能够在实际开发中避免内存泄漏与野指针问题。 💡 学习重点:拷贝构造函数的触发条件、浅拷贝的缺陷、深拷贝的实现方法、赋值运算符的重载原则。 一、拷贝构造函数的概念与触发场景 ✅ 结论:拷贝构造函数是一种特殊的构造函数,用于通过一个已存在的对象创建一个新对象,其参数必须是本类对象的常量引用(const 类名&)。 1.1 拷贝构造函数的语法格式 class 类名 {public:// 普通构造函数 类名(参数列表);// 拷贝构造函数 类名(const 类名& other);}; ⚠️ 注意事项: 1. 拷贝构造函数的参数必须是常量引用,使用 const 防止实参被修改,使用引用避免无限递归调用拷贝构造函数。 2. 如果没有手动定义拷贝构造函数,编译器会自动生成一个默认拷贝构造函数,实现简单的成员变量值拷贝。 1.2 拷贝构造函数的触发条件

By Ne0inhk

C++ const 完整语法整理

C++ const 完整语法整理 const 是 C++ 核心的类型限定符,核心作用是给数据 / 函数添加 “只读” 约束,编译阶段强制检查修改行为,既提升代码安全性、可读性,也帮助编译器做优化。以下按「使用场景」拆解const的语法、作用和核心规则,覆盖从基础到类成员的全场景。 一、核心定义 const(常量)本质是 “只读契约”: * 编译期检查:禁止修改被const修饰的内容,违规直接报编译错误; * 无运行期开销:仅在编译阶段生效,不额外占用内存(除非对const变量取地址 / 声明为全局 / 静态); * 核心价值:避免意外篡改数据、明确函数 “只读行为”、支持 const 对象调用。 二、分场景语法详解 场景 1:const 修饰普通变量(全局 / 局部)

By Ne0inhk
【C++】继承

【C++】继承

目录 一. 概念 二. 基类和派生类对象赋值转换 三. 继承中的作用域 四. 派生类的默认成员函数 1. 构造函数 2. 拷贝构造 3. 赋值重载 4. 析构函数 五. 继承与友元 六. 继承与静态成员 七. 多继承、菱形继承、菱形虚拟继承 虚拟继承解决数据冗余和二义性的原理 八. 继承和组合 一. 概念 继承是类设计层次的复用 语法:Person是父类,也称作基类。Student是子类,也称作派生类 继承关系和访问限定符: 继承以后,保护和私有不一样了 1. 不可见:基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面,都不能去访问它。基类的私有成员在基类中还是能用,在基类外不能用 2. 如果基类成员不想在类外直接被访问,但需要在 派生类中能访问,

By Ne0inhk