【Linux】进程间通信(IPC)-- 无名管道、命名管道

news2025/4/25 1:55:09

IPC机制 实现进程间通信

在多个进程间传输数据或共享信息的机制。

数据交换,共享资源,进程同步,消息传递。

IPC实现原理:通信进程能够访问相同的内存区域。

方法:

管道:无名管道pipe、命名管道FIFO

System V IPC:消息队列、信号量、共享内存

POSIX IPC :消息队列、信号量、共享内存

套接字:socket

一、无名管道pipe

在有父子关系或者有亲缘关系的进程之间通信

字节流通信,数据格式由用户定义/解析

单向通信(半双工模式),数据单向流动(在管道中同时读写会发生错误)

1.创建无名管道 pipe

两种形式

int pipe( int fd[2] ) ;

int pipe( int fd[2] , int flags);

int fd[2]:整型数组,存储管道的文件描述符;fd[0] 读文件描述符,fd[1] 写文件描述符

int flags: 设置管道标志的参数,0或以下参数的按位和:

                O_NONBLOCK 非阻塞 读管道或写管道时不会阻塞管道

                O_CLOEXEC     设置当在execve系统调用执行时关闭管道

返回值:

        成功 返回 0

        失败 返回 -1,并设置errno

2.写管道write
 

#define TEST_STRING "123456789"

void write( fd[1] , TEST_STRING , sizeof(TEST_STRING));

写端fd[1],将TEST_STRING代表的字符写入管道,长度为 sizeof(TEST_STRING)

3.读管道read

char rbuf[100]={0};

void read( fd[0] , rbuf , 100);

读端fd[0] , 将管道中的数据读到rbuf中,每次读100个字符长度

4.关闭管道 close

关闭读端

close(fd[0]);

关闭写端

close(fd[1]);

5.实现父子进程间的半双工通信

以下是父进程和子进程通信,父进程写,子进程读:

无名管道一般跟fork()函数搭配使用。

第一步,调用pipe函数,生成pipeinnode文件节点,生成管道。

第二步,调用fork函数,父进程创建子进程,同时父进程中的文件表也会拷贝到子进程,此时子进程也可以通过fd4,fd5文件描述符访问管道。

第三步,关闭父进程的读端(fd[0]),关闭子进程的写端(fd[1])。
此时父子进程就可以通过管道进行通信。

PS:pipe一定要在fork之前

创建pipe_test文件

vi pipe_test.c

pipe_test文件代码实现

#include <unistd.h>
#include <stdio.h>
#include <string.h>
int fd[2]={};//存储pipe的文件描述符
void pipe_test()
{
	pid_t pid=fork();//创建子进程
	if(pid==0)//子进程
	{       
		printf("children\n");
		close(fd[1]);//子进程关闭写端
		while(1)
		{//读数据
			char rbuf[100]={0};
			read(fd[0],rbuf,100);
			printf("rbuf:%s\n",rbuf);
		}
		close(fd[0]);//读完数据关闭读端
	}
	else if(pid>0)//父进程
	{
		printf("parent\n");
		close(fd[0]);//父进程关闭读端
		#define TEST_STRING "1234567890"
		while(1)
		{
			write(fd[1],TEST_STRING,sizeof(TEST_STRING));
			sleep(1);
		}
		close(fd[1]);
		}
	}
	else
	{}
}

int main(int argc,char * argv[])
{
	int ret=pipe(fd);//创建管道
	if(ret==-1)//创建管道失败
	{
		perror("pipe error");//设置errno
		return -1;
	}
	pipe_test();//调用函数
	return 0;
}

 退出  分别按下按键      Esc : w q
编译 pipe_test文件

gcc -o pipe_test pipe_test.c

运行

./pipe_test

 结果

6.实现父子进程间的全双工通信

如图,父进程和子进程之间能够交换数据,双方都可以向对方写数据和读数据。

第一步,父进程调用两次pipe,创建两个管道。

第二步,父进程调用fork,创建子进程,此时子进程有和父进程相同的文件表,也有两个管道的文件描述符。

第三步,父进程只保留 管道1的读端 和 管道2的写端,

                子进程只保留管道1的写端 和 管道2的读端。

二、命名管道FIFO

无名管道只能在具有亲缘关系的进程之间传递数据,如果想要在不相关的进程之间传递数据,可以使用 FIFO文件 即 “命名管道” (通常也被称为 “有名管道”)完成这项任务。

命名管道是一种特殊类型的文件(别忘了Linux中所有事物都是文件),它在文件系统中以文件名形式存在。文件标识为“p”。


【Linux其他文件类型可查看博客 【Linux】Linux中七种文件类型-CSDN博客】

1.创建FIFO文件

创建FIFO文件 可以在命令行上创建,也可以在程序中创建

(1)在命令行中创建命名管道

在命令行中创建管道也有两种方式

① mkfifo filename
mkfifo filename

filename 是FIFO文件的文件名 

② mknod filename p
mknod filename p

filename 是FIFO文件的文件名

p表示创建的是管道文件 

(2)在程序中创建命名管道

在程序中也有两个函数可以创建命名管道

注意添加头文件

#include <sys/types.h>
#include <sys/stat.h>
① int mkfifo(filename , mode)
int mkfifo (const char * filename , mode_t mode) ;

const char * filename :表示FIFO文件的文件名 

mode_t mode :表示该FIFO文件的文件权限,如可读、可写、可执行

                        命名管道的权限由 mkfifo 的 mode 参数和 umask 共同决定。

                        如    mkfifo(fifo_path, 0666); // 实际权限为 0666 & ~umask

② int mknod(filename , mode | S_IFIFO , 0)

对于这个函数,作者也不太懂,只是看到书上提到了,所以也在这里提出来。对于一般要求可以不掌握。

int mknod (const char * filename , mode_t mode | S_IFIFO , (dev_t) 0) ; 

举例:

创建 fifo_test.c文件

 vi fifo_test.c

fifo_test.c文件 

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
int fifo_test()
{
        const char* fifo_path="./myfifo";
        int ret=mkfifo(fifo_path,0777);
        if(ret<0)
        {
                printf("create myfifo failure\n");
        }
        printf("create myfifo sucessed\n");
        return 0;
}
int main(int argc,char * argv[])
{
        fifo_test();
        return 0;
}

退出  分别按下按键      Esc : w q
编译 fifo_test文件

gcc -o fifo_test fifo_test.c

运行

./fifo_test

 结果

 (在后面的文章中,作者将不再赘叙关于编译运行文件的命令)

2.打开FIFO文件 open

打开FIFO的一个限制是,程序不能以O_RDWR模式(即可读可写模式)打开FIFO文件进行读写操作,这样做的后果未明确定义。但是这个限制是有道理的,如果一个管道以读/写方式打开,那么进程就会从这个管道中读取到它自己写入的数据。

通常使用FIFO文件是为了单向传递数据,要实现全双工模式,跟上文提到的无名管道一样,可以使用一对FIFO文件(即两个FIFO文件)。

int open( const char * filepath , int oflags) ; 

const char * filepath : FIFO文件的路径名

int oflags : 有O_RDONLY ,O_WRONLY ,O_NONBLOCK 三种参数可选可组合(O_RDWR已被排除),共有四种组合方式:

        O_RDONLY : 只读模式。这种情况下open调用将阻塞,除非有一个进程以写的方式打开同一个FIFO,否则将不会返回。

        O_RDONLY | O_NONBLOCK :非阻塞读。即便没有其他进程以写的方式调用FIFO,这个open调用也会成功并立刻返回

        O_WRONLY : 只写模式。这种情况下open调用将阻塞,除非有一个进程以读的方式打开同一个FIFO,否则将不会返回。

        O_WRONLY | O_NONBLOCK :非阻塞写。如果没有其他进程以读的方式调用FIFO,这个open调用将返回错误码-1,并且FIFO也不会打开。如果有一个进程以读的方式打开FIFO文件,就可以通过它的返回的文件描述符对这个FIFO文件进行写操作。

        注意:O_NONBLOCK搭配 O_RDONLY和O_WRONLY的效果是不同的。

                非阻塞读的open调用总是成功的。

                如果没有进程以读的方式打开FIFO文件,那么非阻塞写的open调用将失败。

3.写FIFO文件 write

int pipe_fd = open(FIFO_NAME , open_mode) ; //pipe_fd 为FIFO文件的文件描述符

#define BUFFER_SIZE PIPE_BUF

char buffer[BUFFER_SZIE + 1] ;

write( pipe_fd , buffer , BUFFER_SIZE) ; 

 将 buffer 传入 文件描述符为pipe_fd的命名管道中 , 长度为BUFFER_SIZE。

成功返回0,失败返回-1。

系统对任意时刻在一个FIFO中可以存在的数据长度所有限制的。它由#define PIPE_BUF 语句定义,通常可以在头文件limits.h 中找到它。在Linux系统中,它的值一般为4096字节。

4.读FIFO文件 read

 read函数的用法同write,就是在需要在另一个进程中使读函数。

ret = read(pipe_fd , buffer , BUFFER_SIZE);

5.实现两进程之间的命名管道通信

(1)在命令行中之间使用FIFO通信

① 新建一个myfifo 文件

mkfifo myfifo

② 打开一个终端,将FIFO文件中的内容输出

cat < ./myfifo

③ 打开另一个终端,往FIFO文件中输入

echo "hello world" > ./myfifo 

④ 查看两进程

 (2)在程序中使用FIFO通信

fifocom.c文件

#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/wait.h>
void *writer(void *arg)
{
        printf("ww : writer begin\n");
        const char * fifo_path="./myfifo";
        int fd = open(fifo_path , O_WRONLY);
        if(fd==-1)
        {
                printf("ww: open fifo failure\n");
                exit(-1);
        }
        char * s="hello from writer\n";
        write(fd,s ,strlen(s));
        close(fd);
        printf("ww : close writer\n");
        return NULL;
}
void *reader(void * arg)
{
        printf("rr : reader begin\n");
        const char * fifo_path="./myfifo";
        int fd = open(fifo_path, O_RDONLY);
        if(fd==-1)
        {
                printf("ww: open fifo failure\n");
                exit(-1);
        }
        char  buff[100];
        read(fd, buff, sizeof(buff));
        printf("rr recived: %s\n",buff);
        close(fd);
        printf("rr : close reader\n");
        return NULL;
}
int main(int argc,char * argv[])
{
        printf("everything is ok------\n");
        pthread_t read_thread,write_thread;
        pthread_create(&read_thread , NULL , reader ,NULL);
        pthread_create(&write_thread , NULL , writer ,NULL);

        pthread_join(read_thread ,NULL);
        pthread_join(write_thread ,NULL);
        wait(NULL);
        return 0;
}

结果:

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

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

相关文章

每日一题-力扣-2278. 字母在字符串中的百分比 0331

字母在字符串中的百分比求解方案 | 力扣 2278 题解 问题描述 给定一个字符串 s 和一个字母 letter&#xff0c;我们需要计算 letter 在 s 中出现的百分比&#xff0c;并将结果向下取整。例如&#xff0c;如果字符串是 "foobar"&#xff0c;字母是 "o"&…

关于CodeJava的学习笔记——11

一、GUI 1、最简单的GUI 只有一个按钮的GUI import java.awt.*; import javax.swing.*; public class SimpleGUI{JFrame frame;Button bt;public SimpleGUI(){frame new JFrame("标题栏内容");bt new Button("点我啊");frame.add(bt);frame.setSize(8…

首个物业plus系列展 2025上海国际智慧物业博览会开幕

AI赋能服务升级&#xff01;首个“物业plus”系列展 2025上海国际智慧物业博览会盛大开幕 3月31日&#xff0c;2025上海国际智慧物业博览会&#xff08;简称“上海物博会”&#xff09;在上海新国际博览中心N4馆隆重开幕。本届展会由广州旭杨国际展览有限公司主办&#xff0c…

rk3586开发版新增系统调用(Android13)

一、前言 最近想学一下kernel和hal,所以买了一块板子,带了个摄像头和屏幕,1100,学习投资了。这个Android内核定一个系统调用感觉是真的麻烦&#xff0c;主要是有一层bionic C&#xff0c;一开始不熟悉的时候还是花了点时间去配置。 二、kernel修改 include/uapi/asm-generic…

OCR第三个方案:PP-OCRv4的初步探索

一、PP-OCR历史简要回顾 先请出PP-OCR官网&#xff0c;理解上有出入的&#xff0c;以官网为准。 1.1 PP-OCR系列历史 PP-OCRv1&#xff08;2020&#xff09;&#xff1a;首创3.5M超轻量模型&#xff0c;奠定两阶段架构基础&#xff08;检测方向分类识别&#xff09;PP-OCRv2…

ICLR 2025 Spotlight:让机器人实现「自主进化」,蚂蚁数科、清华提出具身协同框架 BodyGen

最近&#xff0c;全球 AI 和机器学习顶会 ICLR 2025 公布了论文录取结果&#xff1a;由蚂蚁数科与清华大学联合团队提出的全新具身协同框架 BodyGen 成功入选 Spotlight&#xff08;聚光灯/特别关注&#xff09;论文。 论文出自蚂蚁数科与清华大学兴军亮老师团队合作的科研项目…

第十九章:Python-pyttsx3 库实现文本转语音功能

前言 在开发语音交互应用或需要文本转语音功能的项目时&#xff0c;pyttsx3 是一个非常实用的 Python 库。它支持离线语音合成&#xff0c;无需联网即可将文本转换为语音。本文将详细介绍 pyttsx3 的功能、用法以及常见问题的解决方法&#xff0c;并通过示例代码帮助你快速上手…

SvelteKit 最新中文文档教程(16)—— Service workers

前言 Svelte&#xff0c;一个语法简洁、入门容易&#xff0c;面向未来的前端框架。 从 Svelte 诞生之初&#xff0c;就备受开发者的喜爱&#xff0c;根据统计&#xff0c;从 2019 年到 2024 年&#xff0c;连续 6 年一直是开发者最感兴趣的前端框架 No.1&#xff1a; Svelte …

Flutter项目之构建打包分析

目录&#xff1a; 1、准备部分2、构建Android包2.1、配置修改部分2.2、编译打包 3、构建ios包3.1、配置修改部分3.2、编译打包 1、准备部分 2、构建Android包 2.1、配置修改部分 2.2、编译打包 执行flutter build apk命令进行打包。 3、构建ios包 3.1、配置修改部分 3.2、编译…

24、网络编程基础概念

网络编程基础概念 网络结构模式MAC地址IP地址子网掩码端口网络模型协议网络通信的过程&#xff08;封装与解封装&#xff09; 网络结构模式 C/S结构&#xff0c;由客户机和服务器两部分组成&#xff0c;如QQ、英雄联盟 B/S结构&#xff0c;通过浏览器与服务器进程交互&#xf…

Mentalab Explore Pro携手 Wearanize + 数据集,推动睡眠科学研究

在神经科学和睡眠研究的领域&#xff0c;精确监测大脑活动是获取深入见解的关键。传统多导睡眠监测&#xff08;PSG&#xff09;设备虽然提供了详尽的数据&#xff0c;但其操作的复杂性和成本限制了其在更广泛场景中的应用。可穿戴技术的兴起提供了一种新的数据收集方式&#x…

基于 RK3588 的 YOLO 多线程推理多级硬件加速引擎框架设计(代码框架和实现细节)

一、前言 接续上一篇文章&#xff0c;这个部分主要分析代码框架的实现细节和设计理念。 基于RK3588的YOLO多线程推理多级硬件加速引擎框架设计&#xff08;项目总览和加速效果&#xff09;-CSDN博客https://blog.csdn.net/plmm__/article/details/146542002?spm1001.2014.300…

【Yolov8部署】 VS2019+opencv+onnxruntime 环境下部署目标检测模型

文章目录 前言一、导出yolov8模型为onnx文件二、VS2019中环境配置三、源码与实际运行 前言 本文主要研究场景为工业场景下&#xff0c;在工控机与工业相机环境中运行的视觉缺陷检测系统&#xff0c;因此本文主要目的为实现c环境下&#xff0c;将yolov8已训练好的检测模型使用o…

论文阅读:Dual Anchor Graph Fuzzy Clustering for Multiview Data

论文地址:Dual Anchor Graph Fuzzy Clustering for Multiview Data | IEEE Journals & Magazine | IEEE Xplore 代码地址&#xff1a;https://github.com/BBKing49/DAG_FC 摘要 多视角锚图聚类近年来成为一个重要的研究领域&#xff0c;催生了多个高效的方法。然而&#…

乐橙R10 AI智能锁:以「技术减法」终结智能家居「参数内卷」

1 行业迷思&#xff1a;当「技术内卷」背离用户真实需求 “三摄猫眼”、“0.3秒人脸解锁”、“DeepSeek大模型”……智能锁行业的营销话术日益浮夸&#xff0c;但用户体验却陷入“功能冗余”与“操作复杂”的泥潭。 一位用户在社交平台直言&#xff1a;“我的智能锁有六个摄像…

如何使用 FastAPI 构建 MCP 服务器

哎呀&#xff0c;各位算法界的小伙伴们&#xff01;今天咱们要聊聊一个超酷的话题——MCP 协议&#xff01;你可能已经听说了&#xff0c;Anthropic 推出了这个新玩意儿&#xff0c;目的是让 AI 代理和你的应用程序之间的对话变得更顺畅、更清晰。不过别担心&#xff0c;为你的…

当 EcuBus-Pro + UTA0401 遇上 NSUC1500

文章目录 1.前言2.EcuBus-Pro简介2.1 官方地址2.2 概览 3.纳芯微NSUC1500简介3.1 NSUC1500概述3.2 产品特性 4.测试环境5.基础功能5.1 数据发送5.2 数据监控 6.自动化功能6.1 脚本创建6.2 脚本编辑6.3 脚本编辑与测试 7.音乐律动7.1 导入例程7.2 效果展示 ECB工程 1.前言 最近…

【FreeRTOS】裸机开发与操作系统区别

&#x1f50e;【博主简介】&#x1f50e; &#x1f3c5;CSDN博客专家 &#x1f3c5;2021年博客之星物联网与嵌入式开发TOP5 &#x1f3c5;2022年博客之星物联网与嵌入式开发TOP4 &#x1f3c5;2021年2022年C站百大博主 &#x1f3c5;华为云开发…

Deepseek API+Python 测试用例一键生成与导出 V1.0.4 (接口文档生成接口测试用例保姆级教程)

接口文档生成接口测试用例保姆级教程 随着测试需求的复杂性增加,测试用例的设计和生成变得愈发重要。Deepseek API+Python 测试用例生成工具在 V1.0.4 中进行了全方位的优化和功能扩展,特别是对接口测试用例设计的支持和接口文档的智能解析处理。本文将详细介绍 V1.0.4 版本…

CET-4增量表

CET-4词表-增量表 注&#xff1a; 【1】所谓增量&#xff0c;是相对于高中高考之增量 即&#xff0c;如果你是在读大学生&#xff0c;高中英语单词过关了&#xff0c;准备考CET-4&#xff0c;那么侧重下面的增量词表的学习&#xff0c;也算是一条捷径吧 ^_^ 【2】本结果数据 官…