进程间通信之匿名管道和命名管道的理解和实现【Linux】

进程间通信之匿名管道和命名管道的理解和实现

  • 进程间通信
  • 什么是管道
    • 匿名管道
    • 代码实现
    • 管道的读写规则
    • 管道特点
  • 命名管道
    • 创建命名管道
    • 代码实现

进程间通信

进程间通信的目的

  • 数据传输:一个进程需要将它的数据发送给另一个进程
  • 资源共享:多个进程之间共享同样的资源。
  • 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
  • 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。

进程间通信的本质理解

  • 进程间通信的前提,首先需要让不同的进程都能够看到同一块“内存”。
  • 这个“内存”不能隶属于任何进程应该强调共享。

进程间通信的必要性
  单进程无法使用并发能力,更加无法实现多进程协同。

什么是管道

管道是进程通信的其中一种,管道分为两种:

管道
匿名管道pipe
命名管道
  • 管道是Unix中最古老的进程间通信的形式。
  • 我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”。
  • 管道只能单向通信。

在这里插入图片描述

  父进程fork之后,父进程会copy一份files_struct给子进程,但是父子进程的文件描述符依旧是指向同一份文件,而这个文件就叫做管道。
  管道某种意义上来说不是文件,是一种方式,进行交流的数据作为临时数据放在内存,实际上是由内核维护的一个缓冲区,在内核中被称为管道缓存,当交流结束后,临时数据就会被释放。所以也可以把管道看作是一个缓冲区。

匿名管道

#include <unistd.h>
功能:创建一无名管道
原型
int pipe(int fd[2]);
参数
fd文件描述符数组,其中fd[0]表示读端, fd[1]表示写端
返回值:成功返回0,失败返回错误代码

管道的实现
  1. 分别以读写的方式打开同一个文件。
  1. fork创建子进程。
  1. 双方进程各自关闭自己不需要的文件描述符(为了实现单向通信,但是如果想实现全双工通信,可以创建多个管道来实现)。

如何做到让不同的进程看到同一份资源?
:fork后让子进程继承—>能够让具有血缘关系的进程进行进程间通信—>常用于父子进程

在这里插入图片描述

代码实现

下面这是一个简易的匿名管道的实现,当使用pipe函数时,管道文件是通过 pipe 系统调用创建的。具体来说,pipe 系统调用会在内核中创建一个管道,并返回两个文件描述符,这两个文件描述符分别用于读取和写入管道。

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <cstdlib>
int main()
{int fd[2];int retpp = pipe(fd);if (retpp == -1){perror("pipe");exit(1);}int fk = fork();if (fk < 0){perror("fork");exit(2);}if (fk == 0){// child: 作读端,首先得关闭写端close(fd[1]);char buf[1024];read(fd[0], buf, sizeof(buf));printf("child: %s\n", buf);}if (fk > 0){// parent:作写端,首先得关闭读端close(fd[0]);char *bufp = "qwweereewrrere";write(fd[1], bufp, strlen(bufp));return 0;}
}

可不可以改变管道文件呢?
下面的代码将文件t.txt作为管道文件。

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <cstdlib>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{int fd[2];int retpp = pipe(fd);if (retpp == -1){perror("pipe");exit(1);}int fk = fork();if (fk < 0){perror("fork");exit(2);}int fd1 = open("F:\\t.txt", O_RDWR | O_CREAT, 0666);if (fd1 < 0){perror("open");exit(3);}if (fk == 0){// child: 作读端,首先得关闭写端close(fd[1]);char buf[1024];dup2(fd[0], fd1);read(fd[0], buf, sizeof(buf));printf("%s\n", buf);}if (fk > 0){// parent:作写端,首先得关闭读端close(fd[0]);const char *bufp = "qwweereewrrere";dup2(fd[1], fd1);write(fd[1], bufp, strlen(bufp));return 0;}
}

用fork来共享管道原理
在这里插入图片描述
站在文件描述符角度-深度理解管道
在这里插入图片描述

站在内核角度-管道本质
在这里插入图片描述

管道的读写规则

  • 当没有数据可读时
    • O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止。
    • O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN。
  • 当管道满的时候
    • O_NONBLOCK disable: write调用阻塞,直到有进程读走数据
    • O_NONBLOCK enable:调用返回-1,errno值为EAGAIN
  • 如果所有管道写端对应的文件描述符被关闭,则read返回0
  • 如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE,进而可能导致write进程
    退出
  • 当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。
  • 当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。

管道提供了访问控制

  • 写端快,读端慢, 写端满了就不能再写了。
  • 写端慢,读端快, 管道没有数据时,读端必须等待。
  • 写端关闭,读端没有数据可读,标识读到了文件结尾。
  • 读端关闭,写端继续写,OS终止写端进程。

管道特点

  • 只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信;通常,一个管道由一个进程创
    建,然后该进程调用fork,此后父、子进程之间就可应用该管道。
  • 管道提供流式服务
  • 一般而言,进程退出,管道释放,所以管道的生命周期随进程
  • 一般而言,内核会对管道操作进行同步与互斥
  • 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道
    在这里插入图片描述

命名管道

  • 管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
  • 如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。
  • 命名管道是一种特殊类型的文件

创建命名管道

命名管道可以从命令行上创建,命令行方法是使用下面这个命令:
mkfifo filename
命名管道也可以从程序里创建,相关函数有:
int mkfifo(const char *filename,mode_t mode);

比如我们可以这么创建命名管道:

int main(int argc, char *argv[])
{mkfifo("p2", 0644);return 0;
}

匿名管道与命名管道的区别

  • 匿名管道由pipe函数创建并打开。
  • 命名管道由mkfifo函数创建,打开用open
  • FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义。

命名管道的打开规则

  • 如果当前打开操作是为读而打开FIFO时
    • O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO
    • O_NONBLOCK enable:立刻返回成功
  • 如果当前打开操作是为写而打开FIFO时
    • O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO
    • O_NONBLOCK enable:立刻返回失败,错误码为ENXIO

代码实现

  下面的代码实现了客户端向命名管道中写入信息,服务端从命名管道中将数据读取出来并打印在终端屏幕上。

// server.cpp#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <cstdlib>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>int main()
{srand((unsigned int)time(NULL));if (mkfifo("shard", 0666) < 0){perror("mkfifo");exit(1);}int sfd = open("shard", O_WRONLY, 0666);if (sfd < 0){perror("server_open");exit(2);}while (1){int a = rand() % 1000;char server_put[1024] = {'\0'};sprintf(server_put, "%d", a);printf("server: %s\n", server_put);write(sfd, server_put, sizeof(server_put));sleep(2);}return 0;
}
// client#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <cstdlib>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>int main()
{srand((unsigned int)time(NULL));int cfd = open("shard", O_RDONLY, 0666);if (cfd < 0){perror("client_open");exit(2);}while (1){char client_in[1024];read(cfd, client_in, sizeof(client_in));printf("client: %s\n", client_in);sleep(1);}return 0;
}
// makefile.PHANY:all
all: server clientserver:server.cpp g++ -o $@ $^ client:client.cpp g++ -o $@ $^.PHANY:clean
clean:rm -f client server shard

在这里插入图片描述


    😄 创作不易,你的点赞和关注都是对我莫大的鼓励,再次感谢您的观看😄

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

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

相关文章

【obj To 3DTiles 格式转换】 可以自定义经纬高、属性表等参数 (一)

目录 0 引言1 3DTiles数据2 objTo3DTiles2.1 工具的安装2.1.1 拓展&#xff1a;Node.js 和 npm 2.2 工具的使用2.2.1 输出成瓦片数据2.2.2 输出带有坐标参数的瓦片数据 3 查看3DTiles数据 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;Cesiumfor…

谷歌DeepMind最新研究:对抗性攻击对人类也有效,人类和AI都会把花瓶认成猫!

人类的神经网络&#xff08;大脑&#xff09;和人工神经网络&#xff08;ANN&#xff09;的关系是什么&#xff1f; 有位老师曾经这样比喻&#xff1a;就像是老鼠和米老鼠的关系。 现实中的神经网络功能强大&#xff0c;但与人类的感知、学习和理解方式完全不同。 比如ANN表…

上海亚商投顾:创业板指再创调整新低 全市场超4700只个股下跌

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 三大指数1月5日集体调整&#xff0c;沪指午后跌超1%&#xff0c;创业板指一度跌逾2%&#xff0c;尾盘跌幅有所…

.net 开源混淆器 ConfuserEx

官网&#xff1a;ConfuserEx 下载地址&#xff1a;Releases yck1509/ConfuserEx GitHub 使用参考&#xff1a;https://www.cnblogs.com/zhangzhi19861216/p/3937434.html

Windows10安全中心图标的关闭方法

在Windows10​​​​​​​电脑中&#xff0c;用户可以选择关闭不必要的应用图标。现在&#xff0c;用户想要关掉安全中心图标&#xff0c;但不知道有什么方法能够成功关掉安全中心图标&#xff1f;下面小编给用户们带来Windows10系统安全中心图标的关闭方法步骤&#xff0c;帮…

c语言-库函数qsort()初识

目录 前言一、qsort()的介绍及使用1.1 qsort()的介绍1.2 qsort()的使用1.2.1 使用qsort|()对整型数组按照升序排序1.2.2 使用qsort()对整型数组按照降序排序1.2.3 使用qsort()对结构体数组数据进行排序 二、利用冒泡排序模拟实现对任何数据进行排序2.1 冒泡排序2.2 模仿qsort()…

【REST2SQL】04 REST2SQL第一版Oracle版实现

【REST2SQL】01RDB关系型数据库REST初设计 【REST2SQL】02 GO连接Oracle数据库 【REST2SQL】03 GO读取JSON文件 REST2SQL的第一个版本&#xff0c;只支持Oracle数据库&#xff0c;以后会逐步加入其它数据看的支持。 项目文件组织如下&#xff1a; 1 REST2SQL为项目主目录 …

leetcode动态规划问题总结 Python

目录 一、基础理论 二、例题 1. 青蛙跳台阶 2. 解密数字 3. 最长不含重复字符的子字符串 4. 连续子数组的最大和 5. 最长递增子序列 6. 最长回文字符串 7. 机器人路径条数 8. 礼物的最大价值 一、基础理论 动态规划其实是一种空间换时间的基于历史数据的递推算法&…

linux常见操作,and一些练习题加线上练习网站,无须配置linux.持续更新中。。。。

文章目录 cd命令相对路径特殊的路径表达符和cd一起使用pwdmore 查看文件内容支持翻页小技巧clear用户&#xff0c;用户权限 and 用户的切换如何创建用户 ls和通配符的使用利用通配符 *grep 过滤管道符 |如何学习Linux在线练习网站 https://www.lanqiao.cn/courses/1 cd命令 cd…

Basal前端梳理

Basalt前端逻辑梳理 TBB安装参考 https://zhuanlan.zhihu.com/p/480823197 代码注释参考 https://blog.csdn.net/qq_39266065/article/details/106175701#t7 光流追踪参考 https://blog.csdn.net/weixin_41738773/article/details/130282527 VI Odometry KLT tracking 原理 …

第九届中西部外语翻译大赛初赛阶段已经圆满结束

2023年第九届中西部外语翻译大赛&#xff08;以下简称竞赛&#xff09;&#xff0c;于2023年12月30日至31日举行。历届中西部外语翻译大赛均由中西部翻译协会共同体指导发起&#xff0c;各省市译协共建学术指导委员会&#xff0c;获奖证书盖章单位由四川省翻译协会、广西翻译协…

c# 学习笔记 - 集合(List)

文章目录 1.概论1.1 List 特性1.2 .NET API 2. 基本使用2.1 样例 3. 添加类操作3.1 Insert() 4. 删除类操作4.1 Remove()4.2 RemoveAt() 5. 查找类操作6. 排序类操作6.1 Sort(Comparsion<T>) 7. 其他类操作 1.概论 1.1 List 特性 可通过索引访问的强类型列表&#xff0c…

STM32学习笔记二十二:WS2812制作像素游戏屏-飞行射击游戏(12)总结

至此&#xff0c;飞行射击游戏已经基本实现该有的功能&#xff0c;已经比较接近早期的商业游戏了。 如果采用脚本&#xff0c;可以完成关卡游戏&#xff0c;如果不用&#xff0c;也可以做成无限挑战游戏。 我们汇总一下制作的过程&#xff1a; 1、建模UML 2、主循环处理过程…

设计模式篇章(1)——理论基础

设计模式&#xff1a;在软件开发中会面临许多不断重复发生的问题&#xff0c;这些问题可能是代码冗余、反复修改旧代码、重写以前的代码、在旧代码上不断堆新的代码&#xff08;俗称屎山&#xff09;等难以扩展、不好维护的问题。因此1990年有四位大佬&#xff08;GoF组合&…

3的幂00

题目链接 3的幂 题目描述 注意点 无 解答思路 不断除以3直到除数或余数为0为止&#xff0c;判断除完后的数字是否为1 代码 class Solution {public boolean isPowerOfThree(int n) {while (n / 3 ! 0) {if (n % 3 ! 0) {return false;}n n / 3;}return n 1;} }关键点 …

对称加密技术有哪些类型

对称加密是一种加密方式&#xff0c;其加密和解密所使用的密钥是相同的。这种方式的特点是速度快&#xff0c;效率高&#xff0c;适合用于大量数据的加密和解密。对称加密算法有很多种&#xff0c;常见的有AES、DES、3DES等。 对称加密的应用场景非常广泛&#xff0c;下面是一些…

Linux下配置静态ip地址

问题&#xff1a;虚拟机重启后ip地址动态更新&#xff0c;导致连shell十分麻烦 解决&#xff1a; 1. 进入配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens33 2.1 修改配置 BOOTPROTOstatic ONBOOTyes2.2 新增配置 #ip地址(自定义) IPADDR192.168.149.131 #子网掩码 …

2023年12月 C/C++(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C++编程(1~8级)全部真题・点这里 第1题:移动路线 桌子上有一个m行n列的方格矩阵,将每个方格用坐标表示,行坐标从下到上依次递增,列坐标从左至右依次递增,左下角方格的坐标为(1,1),则右上角方格的坐标为(m,n)。 小明是个调皮的孩子,一天他捉来一只蚂蚁,不小心把蚂蚁…

一款开源的MES系统

随着工业4.0的快速发展&#xff0c;制造执行系统&#xff08;MES&#xff09;成为了智能制造的核心。今天&#xff0c;将为大家推荐一款开源的MES系统——iMES工厂管家。 什么是iMES工厂管家 iMES工厂管家是一款专为中小型制造企业打造的开源MES系统。它具备高度的可定制性和灵…

[论文笔记] Qwen-7B tokenizer

https://github.com/QwenLM/Qwen/blob/main/tokenization_note_zh.md#%E6%99%AE%E9%80%9Atoken https://huggingface.co/Qwen/Qwen-7B 一、Qwen-7B 介绍 Qwen-7B采用UTF-8字节级别的BPE tokenization方式,并依赖tiktoken这一高效的软件包执行分词。 Qwen-7B中有两类token,即…