linux——IPC 进程间通信
IPC 进程间通信 interprocess communicate
IPC(Inter-Process Communication),即进程间通信,其产生的原因主要可以归纳为以下几点:
进程空间的独立性
-
资源隔离:在现代操作系统中,每个进程都拥有自己独立的代码和数据空间。这种隔离机制确保了进程之间的安全性和稳定性,但同时也使得进程间无法直接访问对方的资源。
-
资源无法共享:由于进程空间的独立性,一个进程无法直接读取或修改另一个进程的内存空间中的数据。这种情况下,如果需要进行数据交换或共享资源,就需要通过特定的机制来实现。
进程间协作的需求
-
数据交换:在多进程操作系统中,不同的进程可能需要交换数据以完成共同的任务。例如,一个进程可能负责生成数据,而另一个进程则负责处理这些数据。为了实现这种数据交换,就需要使用IPC机制。
-
资源共享:进程间通信还允许进程共享资源,如文件、数据库、内存等。通过IPC,进程可以协调对共享资源的访问,避免冲突和竞争条件。
-
任务协调:在分布式系统或并发编程中,多个进程可能需要协同工作以完成复杂的任务。IPC提供了进程间同步和互斥的机制,确保任务能够按照预定的顺序和条件执行。
IPC的必要性
-
提高系统并发性:通过IPC,多个进程可以并行处理不同的任务,从而提高系统的并发处理能力。
-
优化资源利用:IPC允许进程共享资源,减少了资源的重复分配和浪费,提高了资源利用率。
-
实现复杂功能:在构建复杂的软件系统时,往往需要多个进程协同工作。IPC为这些进程之间的通信和协作提供了必要的支持。
IPC的实现方式
IPC的实现方式多种多样,包括但不限于以下几种:
-
管道(Pipe):一种单向通信方式,常用于具有亲缘关系的进程间通信。
-
消息队列(Message Queue):允许多个进程从同一个队列中读取数据,具有独立性和异步性。
-
共享内存(Shared Memory):一段可以被多个进程同时访问的物理内存区域,提高了进程间的数据交换效率。
-
信号(Signal):一个进程向另一个进程发送信号来传递某种信息或通知某个事件的发生。
-
套接字(Socket):用于不同主机之间的进程通信,提供了网络通信的能
管道==》无名管道、有名管道
无名管道 ===》pipe ==》只能给有亲缘关系进程通信
有名管道 ===》fifo ==》可以给任意单机进程通信
管道的特性:
1、管道是 半双工的工作模式(收或者发)
2、所有的管道都是特殊的文件不支持定位操作。不支持lseek->> fd fseek ->>FILE*
3、管道是特殊文件,读写使用文件IO。fgets,fread,fgetc,
一般情况下使用open,read,write,close;
主要看是否是二进制文件,如果是文本文件使用fges之类的标准io。
注意事项:
1,读端存在,一直向管道中去写,超过64k,写会阻塞。(写的快,读的慢)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{int pipefd[2]={0};int ret = pipe(pipefd);if(-1 == ret){perror("pipe");exit(1);}pid_t pid = fork();if(pid>0){char buf[]="hello,world";close(pipefd[0]);sleep(3);write(pipefd[1],buf,strlen(buf));}else if(0 == pid){close(pipefd[1]);char buf[100]={0};read(pipefd[0],buf,sizeof(buf));printf("pipe %s\n",buf);}else {perror("fork");exit(1);}return 0;
}
2,写端是存在的,读管道,如果管道为空的话,读会阻塞(读的快,写的慢)
读阻塞和写阻塞都是正常情况。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{int pipefd[2]={0};int ret = pipe(pipefd);if(-1 == ret){perror("pipe");exit(1);}pid_t pid = fork();if(pid>0){char buf[1024]={0};close(pipefd[0]);memset(buf,'a',1024);int i = 0 ;for(i=0;i<65;i++){write(pipefd[1],buf,sizeof(buf));printf("i is %d\n",i);}}else if(0 == pid){close(pipefd[1]);char buf[100]={0};
// read(pipefd[0],buf,sizeof(buf));// printf("pipe %s\n",buf);while(1)sleep(1);}else {perror("fork");exit(1);}return 0;
}
3.管道破裂,读端关闭,写管道。
(会导致写关闭,接收端关闭,导致发送端关闭)类似于段错误
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{int pipefd[2]={0};int ret = pipe(pipefd);if(-1 == ret){perror("pipe");exit(1);}pid_t pid = fork();if(pid>0){char buf[]="hello,world";close(pipefd[0]);sleep(3);// 管道破裂 gdb 跟踪write(pipefd[1],buf,strlen(buf));printf("aaaa\n");}else if(0 == pid){close(pipefd[1]);close(pipefd[0]);}else {perror("fork");exit(1);}return 0;
}
4. read 0 ,写端关闭,如果管道没有内容,read 0 ;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{int pipefd[2]={0};int ret = pipe(pipefd);if(-1 == ret){perror("pipe");exit(1);}pid_t pid = fork();if(pid>0){char buf[]="hello,world";close(pipefd[0]);write(pipefd[1],buf,strlen(buf));write(pipefd[1],buf,strlen(buf));close(pipefd[1]);}else if(0 == pid){close(pipefd[1]);char buf[5]={0};while(1){//memset(buf,0,5);bzero(buf,sizeof(buf));int rd_ret = read(pipefd[0],buf,sizeof(buf)-1);if(rd_ret<=0){break;}printf("pipe %s\n",buf);}}else {perror("fork");exit(1);}return 0;
}
if(rd_ret<=0)
{
break;
}
如果读端进程调用read()
函数从管道中读取数据,并且管道已经为空(即没有任何待读取的数据),同时写端已经被关闭,那么read()
函数将会立即返回,并且返回值为0。这个返回值0是一个特殊的信号,它告诉读端进程,管道的写端已经被关闭,并且管道中没有更多的数据可以读取了。
使用框架:
创建管道 ==》读写管道 ==》关闭管道
1、无名管道 ===》管道的特例 ===>pipe函数
特性:
1.1 亲缘关系进程使用
1.2 有固定的读写端
流程:
创建并打开管道: pipe函数
先创建管道再fork();
关闭管道1或者0用,close(xx);
#include <unistd.h>
int pipe(int pipefd[2]);
功能:创建并打开一个无名管道
参数:pipefd[0] ==>无名管道的固定读端
pipefd[1] ==>无名管道的固定写端
返回值:成功 0
失败 -1;
注意事项:
1、无名管道的架设应该在fork之前进行。
无名管道的读写:===》文件IO的读写方式。
读: read()
写: write()
关闭管道: close();
通过管道的方式实现文件的复制:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{int pipefd[2]={0};int ret = pipe(pipefd);if(-1 == ret){perror("pipe");exit(1);}pid_t pid = fork();if(pid>0){close(pipefd[0]);int fd = open("/home/linux/1.png",O_RDONLY);if(-1 == fd){perror("open");exit(1);}while(1){char buf[4096]={0};int rd_ret = read(fd,buf,sizeof(buf));if(rd_ret<=0){break;}write(pipefd[1],buf,rd_ret);}close(fd);close(pipefd[1]);}else if(0 == pid){close(pipefd[1]);int fd = open("2.png",O_WRONLY|O_CREAT|O_TRUNC,0666);if(-1==fd){perror("open");exit(1);}while(1){char buf[1024]={0};int rd_ret = read(pipefd[0],buf,sizeof(buf));if(rd_ret<=0){break;}write(fd,buf,rd_ret);}close(fd);close(pipefd[0]);}else {perror("fork");exit(1);}return 0;
}
验证如下问题:
1、父子进程是否都有fd[0] fd[1],
如果在单一进程中写fd[1]能否直接从fd[0]中读到。
可以,写fd[1]可以从fd[0]读
2、管道的数据存储方式是什么样的
数据是否一直保留?
栈, 先进后出
队列形式存储 读数据会剪切取走数据不会保留
先进先出
3、管道的数据容量是多少,有没有上限值。
操作系统的建议值: 512* 8 = 4k
代码测试实际值: 65536byte= 64k
4、管道的同步效果如何验证?读写同步验证。
读端关闭能不能写? 不可以 ===>SIGPIPE 异常终止 (触发管道破裂)
写端关闭能不能读? 可以,取决于pipe有没有内容,===>read返回值为0 不阻塞
结论:读写端必须同时存在,才能进行
管道的读写。
5、固定的读写端是否就不能互换?
能否写fd[0] 能否读fd[1]? 不可以,是固定读写端。
练习:
如何用管道实现一个双向通信功能
将从父进程发送的消息在发回给父
进程。
pipe,
fork()
if(pid>0)
{
read(file,,)
wirte(fd[1]);
}
if(0 == pid)
{
read(fd[0]);
write(newfile);
}
person
{
char name[];
int age;
char phone;
}
pipe[];
fork();
> 0
fgets 获得输入
填结构体,
写入管道,
==0
read,
填结构体,,
显示到。。。
hello
pipe:hello
wordld
pipe2 ::world;
有名管道===》fifo ==》有文件名称的管道。
文件系统中可见
框架:
创建有名管道 ==》打开有名管道 ==》读写管道
==》关闭管道 ==》卸载有名管道
1、创建:mkfifo
#include <sys/types.h>
#include <sys/stat.h>
remove();
int mkfifo(const char *pathname, mode_t mode);
功能:在指定的pathname路径+名称下创建一个权限为
mode的有名管道文件。
参数:pathname要创建的有名管道路径+名称
mode 8进制文件权限。
返回值:成功 0
失败 -1;
2、打开有名管道 open
注意:该函数使用的时候要注意打开方式,
因为管道是半双工模式,所有打开方式直接决定
当前进程的读写方式。
一般只有如下方式:
int fd-read = open("./fifo",O_RDONLY); ==>fd 是固定读端
int fd-write = open("./fifo",O_WRONLY); ==>fd 是固定写端
不能是 O_RDWR 方式打开文件。
不能有 O_CREAT 选项,因为创建管道有指定的mkfifo函数
3、管道的读写: 文件IO
读: read(fd-read,buff,sizeof(buff));
写: write(fd-write,buff,sizeof(buff));
4、关闭管道:
close(fd);
5、卸载管道:remove();
int unlink(const char *pathname);
功能:将指定的pathname管道文件卸载,同时
从文件系统中删除。
参数: ptahtname 要卸载的有名管道
返回值:成功 0
失败 -1;
open会阻塞,等到另一端读端打开,解除阻塞。
函数是否会阻塞,具体根据操作的对象有关。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, char *argv[])
{int ret = mkfifo("myfifo",0666); if(-1 == ret){//如果是管道文件已存在错误,让程序继续运行if(EEXIST== errno){}else {perror("mkfifo");exit(1);}}//open 会阻塞,等到另一端读段打开,解除阻塞int fd = open("myfifo",O_WRONLY);if(-1 == fd){perror("open");exit(1);}char buf[256]="hello,fifo,test";write(fd,buf,strlen(buf));close(fd);return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>int main(int argc, char *argv[])
{int ret = mkfifo("myfifo",0666); if(-1 == ret){//如果是管道文件已存在错误,让程序继续运行if(EEXIST== errno){}else {perror("mkfifo");exit(1);}}int fd = open("myfifo",O_RDONLY);if(-1 == fd){perror("open");exit(1);}char buf[256]={0};read(fd,buf,sizeof(buf));printf("fifo %s\n",buf);close(fd);//remove("myfifo");return 0;
}
remove可以在命令行调用。
运行方法:
练习:
编写一个非亲缘关系进程间通信程序,可以从
A程序向B程序连续发送不同的数据,并从B中
将发送的信息打印输出,当双方收到quit的时候
程序全部退出。
思考题:
是否每次启动程序必须进行有名管道的创建工作
能否有一个独立的维护工具,可以任意创建并删除
有名管道?
比如:
./fifo_tool -A fifo ==>创建一个有名管道fifo
./fifo_tool -D fifo ==>删除一个有名管道fifo
作业:
有名管道的操作函数封装:
int fifo_read(char *fifoname,void *s,int size);
int fifo_write(char *fifoname,void *s,int size);
编写测试程序验证以上两个函数效果。
gstream
有名管道 ===》
1、是否需要同步,以及同步的位置。
读端关闭 是否可以写,不能写什么原因。
写端关闭 是否可以读。
结论:有名管道执行过程过必须有读写端同时存在。
如果有一端没有打开,则默认在open函数部分阻塞。
2、有名管道是否能在fork之后的亲缘关系进程中使用。
结论: 可以在有亲缘关系的进程间使用。
注意: 启动的次序可能会导致其中一个稍有阻塞。
3、能否手工操作有名管道实现数据的传送。
读: cat fifoname
写: echo "asdfasdf" > fifoname
相关文章:

linux——IPC 进程间通信
IPC 进程间通信 interprocess communicate IPC(Inter-Process Communication),即进程间通信,其产生的原因主要可以归纳为以下几点: 进程空间的独立性 资源隔离:在现代操作系统中,每个进程都…...

JAVA数字化产科管理平台源码:涵盖了孕妇从建档、产检、保健、随访、分娩到产后42天全流程的信息化管理
JAVA数字化产科管理平台源码:涵盖了孕妇从建档、产检、保健、随访、分娩到产后42天全流程的信息化管理 智慧产科管理系统是基于自主研发妇幼信息平台,为医院产科量身打造的信息管理系统,涵盖了孕妇从建档、产检、保健、随访、分娩到产后42天全…...

http数据传输确保完整性和保密性整流程方案(含源码)
往期文章回顾 【深度学习】 【深度学习】物体检测/分割/追踪/姿态估计/图像分类检测演示系统【含源码】【深度学习】YOLOV8数据标注及模型训练方法整体流程介绍及演示【深度学习】行人跌倒行为检测软件系统【深度学习】火灾检测软件系统【深度学习】吸烟行为检测软件系统【深度…...

UE插件与云渲染:10个提升效率的选择
Unreal Engine(虚幻引擎)的插件生态丰富多样,从提升视觉效果到优化工作流程,为开发者提供了无限扩展的可能。本文推荐10款备受欢迎的插件,助你激发创意,提升开发效率. 一、地牢建筑师:程序化关…...

[Shell编程学习路线]——shell脚本中case语句多分支选择详解
🏡作者主页:点击! 🛠️Shell编程专栏:点击! ⏰️创作时间:2024年6月21日16点30分 🀄️文章质量:95分 ————前言———— 在Shell编程中,处理多种条件…...
Django REST Framework(四)DRF Serializer
作用: 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型 3. 反序列化,完成数据校验功能 定义序列化器 Django REST framework中的Serializer使用类来定义&a…...

【C语言】bool 关键字
在C语言中,bool类型用于表示布尔值,即真或假。C语言本身在标准库中并未提供布尔类型,直到C99标准引入了stdbool.h头文件。该头文件定义了bool类型,以及两个常量:true和false。在此之前,通常使用整数来表示布…...

开发电商ERP系统需要接入哪些平台API?
跟随全渠道发展趋势,很多实体商家开设电商店铺,为消费者提供便捷的购物体验,增强消费者的满意度,同时也提升了企业自身的市场竞争力。为了满足商家业务拓展需求,很多原本主要服务于实体商贸企业的ERP服务商,…...

Meet AI4S 直播预告丨房价分析新思路:神经网络直击复杂地理环境中的空间异质性
近年来,房地产市场起起落落,房价已经成为了扰动居民幸福感的重要影响因素。大多数家庭都需要面对「买不买房、何时买房、在哪儿买房、买什么房」的艰难抉择,每一个问题的答案都在某种程度上与房价的波动息息相关。 近年来,我国各…...
支持向量机(SVM)在机器学习中的简单示例
目录 工作原理 核函数 SVM用于分类 结果分析 结论 ❤❤❤动动发财的小手点点赞点点关注哦~~~❤❤❤ 支持向量机是一种强大的监督学习模型,用于分类和回归任务。它通过找到数据点之间的最优边界来区分不同的类别。SVM特别适用于那些具有清晰边界但线性不可分的…...

使用Anaconda虚拟环境安装Opencv、pytorch、torchvision踩坑记录
电脑 python 环境版本过高与下载Opencv(3.4以下)不匹配,因为版本过高部分算法收米, 从而在虚拟环境重新下载python老版本 本文默认您的电脑上已经安装了Anaconda 我是按照这位博文安装的 安装Opencv (详解)安装3.4.1.15版本…...
【人工智能】CPU、GPU与TPU:人工智能领域的核心处理器概述
在人工智能和计算技术的快速发展中,CPU(中央处理器)、GPU(图形处理器)和TPU(张量处理器)作为核心处理器,各自扮演着不可或缺的角色。它们不仅在性能上各有千秋,还在不同的…...
【康复学习--LeetCode每日一题】3099. 哈沙德数
题目: 如果一个整数能够被其各个数位上的数字之和整除,则称之为 哈沙德数(Harshad number)。给你一个整数 x 。如果 x 是 哈沙德数 ,则返回 x 各个数位上的数字之和,否则,返回 -1 。 示例 1&a…...
docker使用jdk21启动jar包报错
[0.007s][warning][os,thread] Failed to start thread "GC Thread#0" - pthread_create failed (EPERM) for attributes: stacksize: 1024k, guardsize: 4k, detached. [0.007s][error ][gc,task ] Failed to create worker thread解决办法 1 (使用doc…...

Object 类中的公共方法详解
Object 类中的公共方法详解 1、clone() 方法2、equals(Object obj) 方法3、hashCode() 方法4、getClass() 方法5、wait() 方法6、notify() 和 notifyAll() 方法 💖The Begin💖点点关注,收藏不迷路💖 在 Java 中,Object…...
python 字典 一个key 多 value 遍历
在Python中,如果一个键对应多个值,你需要确保这些值被存储在一个容器类型(如列表或集合)中。你可以使用默认字典(collections.defaultdict)来简化这个过程。以下是一个示例代码: from collecti…...
vue---基本原理(二)
1、slot的基础理解 slot又名插槽,是vue的内容分发机制,组件内部的模板引擎使用slot元素作为承载分发的出口。是子组件的一个模板标签元素,而这一个标签元素是否显示,以及怎么显示,是由父元素控制的。slot又分为默认插槽…...

桂花网蓝牙网关X1000:引领物联网新时代的智能连接
在物联网技术飞速发展的今天,蓝牙网关作为连接蓝牙设备与互联网的关键设备,其性能与稳定性直接影响到物联网系统的整体运行效果。桂花网蓝牙网关X1000凭借其卓越的性能和广泛的应用场景,成为了物联网领域的佼佼者。 一、产品概述 桂花网蓝牙…...

JAVA案例模拟电影信息系统
一案例要求: 二具体代码(需要在同一个包下创建三个类) Ⅰ:实现类 package 重修;import java.util.Random; import java.util.Scanner;public class first {public static void main(String[] args) {javabean[]moviesnew javabean[4];movies[0] new ja…...
基于Hadoop平台的电信客服数据的处理与分析③项目开发:搭建基于Hadoop的全分布式集群---任务10:Hive安装部署
任务描述 任务内容为安装并配置在Hadoop集群中使用Hive。 任务指导 Hive是一个基于Hadoop的数据仓库框架,在实际使用时需要将元数据存储在数据库中 具体安装步骤如下: 1. 安装MySQL数据库(已安装) 2. 解压缩Hive的压缩包 3…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...