嵌入式 Linux进程之间的通信

news2024/12/25 9:09:02

目录

1、Linux进程间的通信继承

2、Linux进程之间的通信种类 

3、管道

3.1 管道概述

3.2 管道文件

3.3 管道特点

3.4 通信框架 

3.5 对管道文件进行操作 

4、标准流管道

5、无名管道 PIPE

5.1 无名管道特点

5.2 创建管道函数 

6、有名管道(FIFO)

6.1 创建、删除FIFO文件

6.2  打开、关闭FIFO文件 

6.3 读写FIFO文件 


1、Linux进程间的通信继承

  Linux 下的进程通信手段基本上是从 UNIX 平台上的进程通信手段继承而来的。 而对 UNIX 发展做出重大贡献的两大主力 AT&T 贝尔实验室及 BSD(加州大学伯克利分校的伯 克利软件发布中心)在进程间的通信方面的侧重点有所不同。 前者是对 UNIX 早期的进程间通信手段进行了系统的改进和扩充,形成了“system V IPC”, 其通信进程主要局限在单个计算机内。 后者则跳过了该限制,形成了基于套接口(socket)的进程间通信机制。

而 Linux 则把两者的优势都继承了下来,如下图所示,

 

2、Linux进程之间的通信种类 

linux 进程之间的通信主要有下面几种:

通信方式描述
管道 pipe, 命名管道 named pipe管道允许亲缘关系进程间的通信。 命名管道还允许无亲缘关系进程间通信。
信号 signal在软件层模拟中断机制,通知进程某事发生。 它是比较复杂的通信方式,用于通知进程有某事件发生,一个进程 收到一个信号与处理器收到一个中断请求效果上可以说是一样的。
消息队列 message queue是消息的链接表,包括 posix 消息队列和 SystemV 消息队列,它克服了前两种通信方式中信息量有限的缺点。 具有写权限的进程可以按照一定的规则向消息队列中添加新消息。 对消息队列有读权限的进程则可以从消息队列中读取消息。
共享内存 Shared memory可以说是最有用的进程间通信方式,是最快的可用 ipc 形式。 是针对其他通信机制运行效率较低而设计。 它使得多个进程可以访问同一块内存空间,不同进程可以及时看到 对方进程中对共享内存中数据的更新。 这种通信方式需要依靠某种同步机制,如互斥锁和信号量等。
信号量 Semaphore进程间同步。 主要作为进程之间以及同一进程的不同线程之间的同步和互斥手 段。
套接字 socket用于网络中不同机器之间的进程通信

3、管道

3.1 管道概述

管道好比一条水管,有两个端口,一端进水,另一端出水。 管道是 Linux 进程间通信的一种方式,如命令 ps -ef | grep ntp。

3.2 管道文件

我们软件的管道文件也有两个端口,分别是读端和写端。进水可看成数据从写端被写入,出水 可看数据从读端被读出。 在 linux 下文件类型为 p 的文件就是管道文件。

3.3 管道特点

(1)管道通信是单向的,有固定的读端和写端;

(2)数据被进程在管道读出后,管道中的数据就不存在了;

(3)当进程去读取空管道的时候,进程会阻塞;

(4)当进程往满管道写入数据时,进程会阻塞;

(5)管道容量为 64KB (#define PIPE_BUFFERS 16 include/linux/pipe);

3.4 通信框架 

3.5 对管道文件进行操作 

我们分别用 read、 write 函数来对管道的读端和写端进行读写,所以必须要知道读写两端 分别对应的文件描述符。

这两个文件描述符我们通常保存在一个有两个整型元素的数组中,如 int fds[2]; 然后调用函数 pipe(fds),这个函数会创建一个管道,并且数组 fds 中的两个元素会成为管 道读端和写端对应的两个文件描述符。

即 fds[0]和读端相对应, fds[1]和写端相对应。 fds[0]有可读属性, fds[1]有可写的属性。

4、标准流管道

像文件操作有标准 io 流一样,管道也支持文件流模式。 用来创建连接到另一进程的管道 popen 函数和关闭管道函数 pclose。

 如果 open_mode 是“r”,被调用程序的输出就可以被调用程序使用,调用程序利用 popen 函数返回的 FILE*文件流指针,就可以通过常用的 stdio 库函数(如 fread)来读取被调用程 序的输出。 如果 open_mode 是“w”,调用程序就可以用 fwrite 向被调用程序发送数据,而被调用程 序可以在自己的标准输入上读取这些数据。

 这两个函数应用于 Linux 执行 shell 命令的场景。

(1) popen(comm, type)函数会创建一个管道,再 fork 一个子进程,在子进程中执行 execX 函数来执行 comm 命令(因为 execX 执行新程序后新程序的进程空间会覆盖原进程的进程空间,所 以开一个子进程来执行 execX 家族函数),然后想要返回 stdout 或者 stdin 的文件指针(取决于 type); (2) 因为 comm 命令是通过子进程的执行的,那么 stdin 或者 stdout 文件指针也是子进程的 进程片空间的,要将其返回给父进程,这就需要管道了;

(3) stdin 是供程序写数据的,stdout 是供程序读数据的。这里设计的巧妙之处在于,管道 的读端跟 stdout 绑定,管道的写端跟 stdin 绑定;

(4) 读写管道操作的无非就是管道(文件)的 fd(文件描述符),这里将 fd 封装到文件流指针 fp 中; (5) popen 返回的是 stdout,那么 type 为”r”,表示创建一个管道且该管道文件的读端赋 给 fpr; (6) popen 返回的是 stdin,那么 type 为”w”,表示创建一个管道且该管道文件的写端赋 给 fpw; (7) 这样子,读 fpr(管道的读端)等于读子进程的 stdout,写 fpw(管道的写端)等于写子进 程的 stdin。

实例:从标准管道流中读取打印//etc/profile的内容;

#include <stdio.h>
int main()
{
char buf[512] = {0};
FILE* fp = popen("cat /etc/profile", "r"); //执行完这行代码,标准输出就装
满,这里这个标准输出标记为 out1,管道指向 out1,fp 指向管道的读端
//while ((ret = fread(buf, 1, sizeof(buf), fp)) > 0)
//从 out1 中读取 512 个字节数据,存放在 buf
while(fgets(buf, sizeof(buf), fp)){
puts(buf); //输出到终端
}
pclose(fp);
return 0;
}

5、无名管道 PIPE

5.1 无名管道特点

1)只能在亲缘关系进程间通信(父子或兄弟)。

2)半双工(固定的读端和固定的写端)。

3)它是特殊的文件,可以用 read、write 等函数操作,这种文件只能在内存中。

5.2 创建管道函数 

管道函数原型:

#include <unistd.h>
int pipe(int fds[2]);

函数 pipe 用于创建一个无名管道,如果成功, fds[0]存放可读的文件描述符,fds[1]存 放可写文件描述符,并且成功返回 0,否则返回-1。 通过调用 pipe 函数获取这对打开的文件描述符后,一个进程就可以从 fds[0]中读数据,而 另一个进程就可以往 fds[1]中写数据。 当然两进程间必须有继承关系,才能继承这对打开的文件描述符。

 管道不象真正的物理文件,不是持久的,即两进程终止后,管道也自动消失了。

示例:创建父子进程,创建无名管道,父写子读。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main()
{
int fds[2] = {0};
pipe(fds);
char buf[32];
if(fork() == 0){
sleep(2); //保证父进程有机会把数据写入
read(fds[0], buf, sizeof(buf)); //子进程从读端读数据
puts(buf);
close(fds[0]);
close(fds[1]);
}
else{
write(fds[1], "hello", 6); //父进程向写端写数据
waitpid(-1, NULL, 0); //等子退出
close(fds[0]);
close(fds[1]);
}
return 0;
}

注意: 管道两端的关闭是有先后顺序的。 如果先关闭写端则从另一端读数据时,read 函数将返回 0,表示管道已经关闭; 但是如果先关闭读端,则从另一端写数据时,将会使写数据的进程接收到 SIGPIPE 信号,如 果写进程不对该信号进行处理,将导致写进程终止,如果写进程处理了该信号,则写数据的 write 函数返回一个负值,表示管道已经关闭。

6、有名管道(FIFO)

  无名管道只能在亲缘关系的进程间通信,这大大限制了管道的使用,有名管道突破了这个限制, 通过指定路径名的形式实现不相关进程间的通信。

6.1 创建、删除FIFO文件

创建 FIFO 文件与创建普通文件很类似,只是创建后的文件用于 FIFO。

1)用函数创建和删除 FIFO 文件 创建 FIFO 文件的函数原型如下:

#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
形参:
pathname 要创建的 FIFO 文件的全路径名;
mode 为文件访问权限,比如 0666。
返回值:
如果创建成功,则返回 0,否则-1。

删除 FIFO 文件的函数原型如下:

#include int unlink(const char *pathname);

跟 mkfifo 的第一个形参一样。

示例:用函数创建FIFO文件

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc,char *argv[]) //演示通过命令行传递参数
{
if(argc != 2){
puts("arg cnt err:");
return -1;
}
if(mkfifo(argv[1], 0666) == -1){
perror("mkfifo fail");
return -2;
}
//unlink(argv[1]);//加上这句会将创建的 FIFO 文件删除。
return 0;
}
/*
说明 :创建名字为 2 的 FIFO 文件
[root@localhost test]# gcc -o main main.c
[root@localhost test]# ./main 2 */

2)用命令创建和删除 FIFO 文件 用命令 mkfifo 创建 fifo 文件,不能重复创建。 用命令 unlink 删除 fifo 文件。 创建完毕之后,就可以访问 FIFO 文件了:

一个终端:cat < myfifo //输出 另一个终端:echo “hello” > myfifo //输入

6.2  打开、关闭FIFO文件 

对 FIFO 类型的文件的打开/关闭跟普通文件一样,都是使用 open 和 close 函数。

1)如果打开时使用 O_WRONLY 选项,则打开 FIFO 的写入端,

2)如果使用 O_RDONLY 选项,则打开 FIFO 的读取端,

3)写入端和读取端都可以被几个进程同时打开。

该管道可以通过路径名来指出,并且在文件系统中是可见的。 在建立了管道之后,两个进程就可以把它当作普通文件一样进行读写操作,使用非常方便。

注意:

1)FIFO 是严格地遵循先进先出规则。

2)对管道及 FIFO 的读总是从该文件开始处返回数据。

3)对它们的写则把数据添加到该文件末尾。

4)它们不支持如 lseek()等文件定位操作。

6.3 读写FIFO文件 

可以采用与普通文件相同的读写方式读写 FIFO。

示例: 先执行#mkfifo f.fifo 命令,创建一个 FIFO 文件。 编写 write.c,如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd = open("f.fifo", O_WRONLY); //1. 打开(判断是否成功打开略)
write(fd, "hello", 6); //2. 写
close(fd); //3. 关闭
return 0;
}

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

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

相关文章

FPGA lattice 深力科LCMXO3LF-2100C-5BG324I拥有很强的灵活性和适应性可编程内核的FPGA 值得期待

FPGA lattice 深力科LCMXO3LF-2100C-5BG324I MachXO3系列 拥有很强的灵活性和适应性可编程内核的FPGA 值得期待 &#xff0c;FPGA 现场可编程逻辑器件,小尺寸&#xff0c;高性能&#xff01;在工业领域&#xff0c;它可以用于网络控制器&#xff0c;PLC,网络边缘计算&#xff0…

kubernetes--分析容器系统调用:Sysdig

目录 Sysdig介绍&#xff1a; sysdig工作流程 安装Sysdig sysdig常用参数&#xff1a; sysdig过滤&#xff1a; sysdig之Chisels&#xff08;工具箱&#xff09;&#xff1a; 其他常用命令 Sysdig介绍&#xff1a; Sysdig是一个非常强大的系统监控分析和故障排查工具。汇…

MOEA/D: A Multiobjective Evolutionary Algorithm Based on Decomposition

目录1 问题定义2 算法步骤3 代码4 效果1 问题定义 本博客以最小化问题为例 f1x2f2(x−2)2min⁡f(f1(x),f2(x))\begin{aligned} f_1 & x ^2 \\ f_2 & (x - 2) ^2 \\ \min f & (f_1(x), f_2(x)) \end{aligned} f1​f2​minf​x2(x−2)2(f1​(x),f2​(x))​ 代码…

二十、常用调优工具概述与Jprofiler演示

常用调优工具 1.JDK命令行 2.Eclipse:Memory Analyzer Tool 3.Jconsole 4.VisualVM 5.Jprofiler 6.Java Flight Recorder 7.GCViewer 8.GC Easy jprofiler 简介&#xff1a; 他把CPU、执行引擎和内存的剖析组合在一个强大的应用中。JProfiler可提供许多IDE整合和应用服务器整合…

集成学习boosting、bagging、stacking

目录 一、介绍 二、三种架构学习 &#xff08;1&#xff09;boosting &#xff08;2&#xff09;bagging &#xff08;3&#xff09;stacking 一、介绍&#xff1a; 对于单个模型来说很难拟合复杂的数&#xff0c;模型的抗干扰能力较低&#xff0c;所以我们希望可以集成多…

ElasticSearch 8 学习笔记总结(五)

文章目录一、ElasticSearch 8 版本二、ES8 集群 环境安装1. 生成安全证书2. 生成http证书3. 配置第一个节点4. 配置其他节点三、ES集群 关联问题解决四、 Kibana 安装和使用五、kibana 基础操作1. 索引操作2. 文档操作3. 文档搜索4. 索引模板六、分词器七、文档评分机制1. 什么…

上拉电阻与下拉电阻总结

文章目录相关概念介绍IO引脚的三态输出之高阻态---将逻辑门与系统其他部分隔离&#xff0c;电平外部控制IO引脚输出模型 推挽电路 与 开漏电路---单独开漏无高电平驱动能力原理介绍什么是上下拉电阻&#xff1f;---把IO口用电阻拉到正压VCC&#xff08;上拉&#xff09; 或 接地…

如何使用Docker容器部署O2OA(翱途)开发平台与OnlyOffice的集成版本?

O2OA(翱途)开发平台[下称O2OA平台或者O2OA]默认可以和OnlyOffice进行集成来实现在线文档编辑以及流程集成。开发者可以直接安装O2OA官网的OnlyOfficeO2Server的Docker版本用于体验。本文将详细介绍如何安装O2OA OnlyOffice的Docker版本。OnlyOffice Docs Sever可以单独安装,O2…

aws apigateway 使用httpapi私有集成ecs服务

参考资料 https://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/http-api-private-integration.htmlhttps://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/http-api-develop-integrations-private.html 在《aws apigateway 基础概念和入门示…

Vue2.0开发之——购物车案例-Goods组件封装-把购买数量传给counter组件(52)

一 概述 Goods组件中导入Counter组件设置Counter组件的数量 二 Goods组件中导入Counter组件 2.1 Goods组件中导入Counter组件 import Counter from "/components/Counter/Counter.vue";2.2 Goods组件中注册Counter组件 components:{Counter }2.3 Goods组件中使用…

GDKOI2023游记+一周模拟赛题解

温馨提示&#xff1a; 1)有些链接需要在本校OJ上的博客里才能打开。2)没更新完。 Day -6&#xff08;3.4&#xff09; 晚上打了场AtCoder&#xff0c;rank1515rank 1515rank1515&#xff0c;切了5题&#xff0c;信心。 zswangziye的atcoder账号 打T5的时候心态不稳&#xff…

2022年MathorCup数学建模A题大规模指纹图像检索的模型与实现解题全过程文档加程序

2022年第十二届MathorCup高校数学建模 A题 大规模指纹图像检索的模型与实现 原题再现 在生物特征识别领域&#xff0c;指纹作为最具独特性与持久性的生物特征之一&#xff0c;被广泛应用于身份识别。   指纹识别过程分为特征提取和比对两个环节。其中特征提取环节会提取用于…

matplotlib: 绘制柱状图

通过matplotlib绘制柱形图 第一个例子 from matplotlib import pyplot as plty [10, 11, 12, 11, 9, 8, 13, 10] # 创建y轴坐标 x list(range(1,9)) # 创建x轴坐标# 创建x轴显示的参数&#xff08;此功能在与在图像中x轴仅显示能被10整除的刻度&#xff0c;避免刻度过多分…

比亚迪:全球最大电动汽车制造商的坎坷成长之路

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 特斯拉&#xff08;TSLA&#xff09;首席执行官埃隆马斯克表示&#xff0c;特斯拉最接近的竞争对手可能是一家中国电动汽车公司。猛兽财经认为&#xff0c;沃伦•巴菲特支持的比亚迪&#xff08;0211&#xff09;可能是马斯…

在ubuntu上部署与使用docker(python)

1.安装Docker首先&#xff0c;更新现有的包列表sudo apt update接下来安装一些允许童HTTPS才能使用的软件包&#xff1a;sudo apt install apt-transport-https ca-certificates curl software-properties-common然后将官方Docker存储库的GPG秘钥添加到您的系统curl -fsSL http…

关于 C# 引用参数和值参数

关于 C# 引用参数和值参数 C# 数据类型分为值类型和引用类型&#xff0c;两者的区别在于值类型的数据存储在栈中&#xff0c;而引用类型的数据存储在堆中&#xff0c;但是栈中会存放指向存储数据的堆的位置。 传递参数时&#xff0c;传递的是数据栈中的值&#xff0c;实参将数…

高等数学——一元函数微分学

文章目录导数与微分概念几何意义连续、可导、可微之间的关系求导法则基本初等函数的导数公式有理运算法则复合函数求导法奇偶性和周期性隐函数求导反函数求导参数方程求导对数求导法高阶导数概念常用的高阶导数公式微分中值定理和导数的应用微分中值定理导数的应用函数的单调性…

巾帼绽芬芳 一起向未来(下篇)

编者按&#xff1a;为了隆重纪念纪念“三八”国际妇女节113周年&#xff0c;快来与你全方位、多层次分享交流“三八”国际妇女节的前世今生。分上篇&#xff08;节日简介、节日发展和节日意义&#xff09;、中篇&#xff08;节日活动宗旨和世界各国庆祝方式&#xff09;和下篇&…

Linux学习第二十节-NTP网络时间协议

1.概念 NTP(Network Time Protocol&#xff09;网络时间协议基于UDP用于网络时间同步的协议&#xff0c;使网络中的计算机时钟同步到UTC(世界统一时间)&#xff0c;再配合各个时区的偏移调整就能实现精准同步对时功能。 chrony是网络时间协议NTP的实现方式&#xff0c; Chron…

three.js 纹理贴图的使用

刚刚入门的小伙伴请先查看 three.js 基础认识与简单应用 本文章中的两个注意点&#xff0c;下面也有提到&#xff0c;分别是&#xff1a; 1、 vue项目中使用的贴图路径-->需要把 static文件夹 放到 public文件夹下,并使用 static 开头的绝对路径。 2、使用环境遮挡贴图时&a…