linux---进程间通信(ipc)之管道

2023-05-16

  1. 进程间通信方式
  • 管道
  • 共享内存
  • 消息队列
  • 信号量
  • 本地套接字等等都能作为我们进程间通信的方法
  1. 操作系统提供进程间通信方式的原因
    因为对于我们进程来说,每一个进程都是相互独立的,具有独立性,如果我们需要两个不同的进程相互通信,就需要我们操作系统提供一个公共的媒介,这个媒介就是进程间通信方式
  2. 进程间通信是干什么的?
    通过进程间通信我们可以对不同进程进行数据传输,数据共享,进程控制,时间通知,不同的进程间通信方式不同我们的功能也有所差异

管道

  1. 管道的本质
    管道其实就是内核中的一块缓冲区,我们通过对这块缓冲区的操作来达到我们的进程间通信的目的
    在这里插入图片描述
    对缓冲区的操作其实就是对我们的I/O操作,但我们的管道是双向选择半双工方式工作,因为在同一个时刻我们只能对我们的一端只进行读或者写操作,不能对我们的一端又读又写。我们管道又分为匿名管道和有名管道。

匿名管道

匿名管道只能用于有血缘关系的进程中的通信,因为匿名管道创建缓冲区的时候没有名字,对于非血缘的进程找不到这款缓冲区,所有我们就不能再非血缘进程中进行同行。

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

pipefd是传入参数,得到的是我们操作的读写文件描述符,
返回值:成功返回0,失败返回-1
pipe()是在内核中建立一块缓冲区并且利用传入参数返回这个缓冲区的文件描述符。
例子:使用匿名管道实现ps | grep命令

 1. #include <stdio.h>                                                                                
  2 #include <unistd.h>
  3 #include <stdlib.h>
  4 #include <errno.h>
 int main()
  7 {
  8     int fd[2];
  9 
 10     int ret = pipe(fd);
 11     if (ret < 0) {
 12         perror("pipe error");
 13         return -1;
 14     }
 15     int pid1 = fork();
 16     if (pid1 == 0) {
 17         //child1--  ps -ef 
 18         close(fd[0]);
 19         dup2(fd[1], 1);
 20         execlp("ps", "ps", "-ef", NULL);
 21         exit(0);
 22     }
 23     int pid2 = fork();
 24     if (pid2 == 0) {
 25         //child2--  grep pipe
 26         close(fd[1]);
 27         dup2(fd[0], 0);
 28         execlp("grep", "grep", "bash", NULL);
 29         exit(0);
 30     }
 31     close(fd[0]);
 32     close(fd[1]);
 33     waitpid(pid1, NULL, 0);
 34     printf("child1 exit--------\n");
 35     waitpid(pid2, NULL, 0);
 36     printf("child2 exit--------\n");
 37     return 0;
 38 }  
         exit(0);
 22     }
 23     int pid2 = fork();
 24     if (pid2 == 0) {
 25         //child2--  grep pipe
 26         close(fd[1]);
 27         dup2(fd[0], 0);
 28         execlp("grep", "grep", "bash", NULL);
 29         exit(0);
 30     }
 31     close(fd[0]);
 32     close(fd[1]);
 33     waitpid(pid1, NULL, 0);
 34     printf("child1 exit--------\n");
 35     waitpid(pid2, NULL, 0);
 36     printf("child2 exit--------\n");
 37     return 0;
 38 }  

有名管道

为我们的管道创建一个管道文件,这个管道文件就是管道的名字,因为有了名字,所以在我们的有名管道中我们可以在任意的进程间都可以实现我们的进程间通信。

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

pathname:管道文件名称
mode:管道文件的权限
在这里插入图片描述
其实原理还是和匿名管道是一样的,在内核中创建一块缓冲区使得我们操作缓冲区的时候我们可以进行进程间的通信,但是此时的缓冲区变得有名字了,这时候不再是只有血缘关系的进程才能通信,现在是所有的进程都能进行通信,只要能找到我们对应的缓冲区文件fifio.
实现我们有名管道进程间的通信

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
int main(){
	char* filename = "pipe.fifo";
	int ret =  mkfifo(filename,664);
	if(ret == -1){
		if(errno != EEXIST){
			perror("mkfifo error\n");
			return -1;
		}
	}
	//创建fifo成功
	int fd = open(filename,O_WRONLY);
	if(fd == -1){
		perror("open error\n");
		return -1;
	}
	printf("打开文件成功\n");
	while(1){
		char buf[1024];
		scanf("%s",buf);
		write(fd,buf,strlen(buf));
	}
	close(fd);
	return 0;
}

此时我们想我们的缓冲区中写入数据,

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
int main(){
	char * filename = "./pipe.fifo";
	int ret = mkfifo(filename,664);
	if(ret == -1){
		if(errno != EEXIST){
			perror("mkfifo error\n");
			return -1;
		}
	}
	printf("打开fifo文件成功\n");
	int fd = open(filename,O_RDONLY);
	if(fd == -1){
		perror("read error\n");
		return -1;
	}
	while(1){
		sleep(1);
		char* buf[1024];
		ret = read(fd,buf,sizeof(buf));
		if(ret == 0){
			printf("写入端已经关闭\n");
			exit(0);
		}
		if(ret == -1){
			perror("read error\n");
			return -1;
		}
		printf("buf:[%s\n]",buf);
	}
	close(fd);
	return 0;
}

读取我们write进程写入到我们的缓冲区的内容。

管道特性

对于我们的有名管道,如果管道文件没有被写的方式打开,则以只读的方式打开会阻塞;如果没有被读的方式打开,则以只写打开会阻塞
对于匿名管道来说只有读写特性,有名管道的读写特性和匿名管道是一样的。

  • 读写特性
  1. 管道中没有数据的时候,read()会阻塞,直到读取到数据。
  2. 管道中若数据满了,write会阻塞知道有空闲空间
  3. 所有读端被关闭,write会触发异常
  4. 所有写端被关闭,read读完数据不会阻塞,而是返回0
  • 管道总结
  1. 匿名管道只能用于血缘关系的进程通信,有名管道可以用于任意的进程通信
  2. 管道读写特性+有名管道的打开特性
  3. 管道是半双工通信,但是双向选择
  4. 管道的生命周期随着进程
  5. 管道提供流式服务
  6. 管道自带同步与互斥功能(体现在没有数据则读会阻塞,放了数据之后唤醒我们的对象阻塞,对方读数据(同步);数据往管道中没放完别人不能去操作(互斥))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux---进程间通信(ipc)之管道 的相关文章

  • 如何在 Linux 中使用单行命令获取 Java 版本

    我想通过单个命令获取 Linux 中的 Java 版本 我是 awk 的新手 所以我正在尝试类似的事情 java version awk print 3 但这不会返回版本 我将如何获取1 6 0 21从下面的Java版本输出 java ve
  • 远程linux服务器到远程linux服务器大型稀疏文件复制 - 如何?

    我有两台 CentOS 5 4 服务器 每台服务器上都安装了 VMware Server 假设我始终对 vmware 虚拟机使用稀疏文件 将虚拟机文件从一台服务器复制到另一台服务器的最可靠 最快速的方法是什么 虚拟机的文件复制起来很痛苦 因
  • Linux 文本文件操作

    我有一个格式的文件 a href a href a href a href 我需要选择 之后但 之前的文本 并将其打印在行尾 添加后 例如 a href http www wowhead com search Su a a a a a
  • 是否有可能在linux中找到包含特定文本的文件?

    考虑这种情况 我在文件夹 Example 下有很多文件 如果我需要找到一个包含特定短语 如 Class Example 的文件 我该如何使用 Linux shell 来做到这一点 linux中有类似 定位 的函数可以做到这一点吗 Thank
  • R 未获取用户库

    我有一个带 R 3 6 0 的 Fedora 30 系统 用户库设置在Renviron就像这个 R LIBS USER R LIBS USER R x86 64 redhat linux gnu library 3 6 事实上 它出现在交互
  • Linux、ARM:为什么仅当启动时存在 I2C GPIO 扩展器时才创建 gpiochip

    在 imx6sx 硬件平台 NXP 嵌入式 ARM 上使用 Linux 3 14 52 问题是设备树中指定的 PCF8575 I2C GPIO 扩展器不会实例化为 sys class gpio 结构中的设备 除非它们在内核启动期间存在 这些
  • 无关的库链接

    我有一个可能有点愚蠢的问题 因为我很确定我可能已经知道答案了 假设你有静态库A 动态共享库B和你的linux下的程序C 假设库 A 调用库 B 中的函数 并且您的程序调用库 A 中的函数 现在假设 C 在 A 中调用的所有函数都不使用 B
  • 具有少量父设备属性的 udev 规则

    我需要复杂且通用的udev规则来确定插入任何 USB 集线器的特定端口的 USB 设备 所以 我必须结合设备树不同层的父属性 我有这个 udevadm info query all name dev ttyUSB0 attribute wa
  • 确保 config.h 包含一次

    我有一个库项目 正在使用 Linux 中的 autotools 套件移植到该项目 我对自动工具很陌生 本周 我已经了解了其操作的基础知识 我有一个关于如何保留内容的问题config h免遭重新定义 我惊讶地发现生成的config h文件也没
  • 如何在 Linux 主机上的 docker 容器中挂载目录 [重复]

    这个问题在这里已经有答案了 我想将一个目录从 docker 容器挂载到本地文件系统 该目录是网站根目录 我需要能够使用任何编辑器在本地计算机上编辑它 我知道我可以跑docker run v local path container path
  • Linux 上的 Python 3.6 tkinter 窗口图标错误

    我正在从 Python GUI 编程手册 学习 Python GUI 某项任务要求我通过将以下代码添加到我的配方中来更改窗口图标 Change the main windows icon win iconbitmap r C Python3
  • 如何从linux命令行运行.exe可执行文件? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我在 Windows 中有一个 abc exe 可执行文件 我可以使用 DOS 命令提示来执行此应用程序 并为其提供一些运行时变量 我想从
  • 如何调用位于其他目录的Makefile?

    我正在尝试这样做 我想打电话给 make Makefile存在于其他目录中 abc可以使用位于不同目录中的 shell 脚本的路径 我该怎么做呢 由于 shell 脚本不允许我cd进入Makefile目录并执行make 我怎样才能编写she
  • touch命令在一个目录下创建多个文件(不同名称)

    我想制作一个在 bash 中创建目录和文件结构的脚本 我尝试过这样的事情 mkdir p 1 2 touch 1 2 a b c a b c 应该是在一个命令或其他命令中创建的文件 但由于某种原因 结构是这样的 current folder
  • 如何获取 linux 实用程序 tail 的源代码?

    这个命令确实非常有用 但是我可以在哪里获取源代码以查看内部发生的情况 thanks tail 实用程序是 Linux 上 coreutils 的一部分 源压缩包 ftp ftp gnu org gnu coreutils coreutils
  • 如何用X11复制到剪贴板?

    使用 OS X 上的框架 我可以使用以下命令将 PNG 复制到粘贴板 在 C 中 显然我可以将 NSPasteboard 与 Cocoa 一起使用 include
  • 停止服务时单元陷入故障状态(状态=143)[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 这是我的问题 我有 CentOS 和 java 进程在上面运行 Java进程是通过启动 停止脚本来操作的 它也创建了 java 实例的 p
  • Linux shell 脚本:十六进制数字到二进制字符串

    我正在 shell 脚本中寻找一些简单的方法来将十六进制数字转换为 0 和 1 字符的序列 Example 5F gt 01011111 是否有任何命令或简单的方法来完成它 或者我应该为其编写一些开关 echo ibase 16 obase
  • 如何让“grep”从文件中读取模式?

    假设有一个很大的文本文件 我只想打印与某些模式不匹配的行 显然 我可以使用egrep v patter1 pattern2 pattern3 现在 如果所有这些模式都在一个文本文件中怎么办 最好的制作方法是什么egrep从文件中读取模式 g
  • sleep 0 有特殊含义吗?

    我看到很多用法sleep 0在我的一个客户项目中 代码看起来像这样 while true sleep 0 end 阅读一些像这样的答案this https stackoverflow com questions 3727420 signif

随机推荐

  • 2.树莓派系统备份

    树莓派使用SD卡来装载系统 xff0c 如果SD卡丢失或者损坏 xff0c 那么树莓派上的数据都会丢失 xff0c 所以一定要备份好SD卡 这篇文章可以帮你备份你的树莓派系统 主要内容为备份SD卡 xff0c 制作树莓派系统镜像以及在需要的
  • ic_gvins编译及环境配置问题解决

    RTK VIO松组合 对惯导精度要求较高 1 环境配置和编译 安装依赖项 span class token comment gcc 8 span span class token function sudo span span class
  • EVO画图设置

    一 绘图设置 1 更改背景色和网格 span class token comment 白色网格 span evo config span class token builtin class name set span plot seabor
  • GINS_OB环境配置

    1 程序简介 武大开源GNSS INS松组合IMU预积分有考虑地球自传和不考虑两种形式可以灵活设置GNSS中断时间IMU可以和里程计进行融合 2 环境配置 span class token comment gcc 8 g 43 43 8 s
  • OB_GINS程序框架

    1 程序运行 span class token builtin class name cd span OB GINS span class token comment 编译好的可执行文件 xff1a bin ob gins xff0c 参数
  • KEIL、MDK中关于__LINE__宏 printf 的显示不正确的问题

    span class token operator gt span define span class token function DEBUG span span class token punctuation span log span
  • VINS-回环检测与重定位

    参考博客 pose graph分析1 pose graph分析2 pose graph分析3
  • 源码安装naviagtion,但是出现[move_base-2] process has died 运行错误的解决办法

    今天开始记录ros遇到的问题 安装navigation可以使用两种方法 第一种 xff1a sudo apt get install ros kinetic navigation 这种安装方法最简单 xff0c 新手或者不需要动naviag
  • linux---静态库和动态库的制作和使用

    静态链接和动态链接 静态链接 xff1a 生成可执行代码 xff0c 链接静态库 xff08 与代码位置有关的链接方式 xff09 xff0c 需要将代码拷贝到我们的源代码中才能运行 动态链接 xff1a 生成可执行代码 xff0c 链接动
  • 加一

    加一 描述 给定一个由整数组成的非空数组所表示的非负整数 xff0c 在该数的基础上加一 最高位数字存放在数组的首位 xff0c 数组中每个元素只存储单个数字 你可以假设除了整数 0 之外 xff0c 这个整数不会以零开头 示例 1 输入
  • STM32bootloader原理解释

    STM32bootloader原理解释 一 STM32的常规启动流程 STM32的内部flash地址起始于0x8000000 xff0c 一般情况下 xff0c 程序文件就从此地址开始写入 此外STM32是基于Cortex M3内核的微控制
  • 模糊PID基本原理及matlab仿真实现(新手!新手!新手!)

    有关模糊pid的相关知识就把自己从刚接触到仿真出结果看到的大部分资料总结一下 xff0c 以及一些自己的ps 以下未说明的都为转载内容 1 转自 https blog csdn net weixin 36340979 article det
  • VMware+ubuntu+win10笔记本实现笔记本连接WIFI且ubuntu既可以上网又能连接开发板

    背景 最近在学习imx6ull开发板的时候 xff0c 发现开发板通过网线连接笔记本电脑却无法ping通ubuntu xff0c 于是捣鼓了很久终于可以了 xff0c 却又发现ubuntu不能上网了 xff0c 经过一番查找资料和尝试 xf
  • 在windows上用vscode打造比vc++6.0好用的C/C++ IDE,适用编程小白

    准备 xff1a 1 安装MinGW xff0c 添加gcc gdb等编译调试工具bin目录 头文件Include目录 库lib的路径到系统环境变量 xff0c 安装LLVM 添 加Clang编译器所在bin目录到系统环境变量 具体操作百度
  • C语言数据结构——线性表的链式存储结构

    文章目录 线性表的链式存储结构1 基本概念2 设计与实现3 优点和缺点 线性表的链式存储结构 1 基本概念 链式存储定义 xff1a 为了表示每个数据元素与其直接后继元素之间的逻辑关系 xff0c 每个元素除了存储本身的信息之外 xff0c
  • 智能车浅谈——硬件篇

    目录 初识小车硬件系统1 电源系统线性电源开关电源 2 人机交互系统3 MCU最小系统4 传感器系统摄像头电感编码器 5 驱动系统 机械结构 17届完赛代码智能车系列文章汇总 前言 xff1a 作为一名老三本玩家 xff0c 笔者深知一些同
  • 智能车浅谈——图像篇

    文章目录 前言认识图像基本含义图像类型数字图像彩色图像灰度图像黑白图像 小结 图像处理图像压缩二值化固定阈值法大津法 图像降噪 xff08 腐蚀 xff09 寻边线 总结17届完赛代码17届完赛代码智能车系列文章汇总 前言 前面已经记录了智
  • 智能车浅谈——手把手让车跑起来(电磁篇)

    文章目录 前言材料准备备赛组车模硬件 练习组车模硬件方案 整车原理赛道信息获取及转向原理工字电感运放模块转向原理元素判断 电机及舵机控制原理 代码实现效果欣赏总结17届完赛代码智能车系列文章汇总 前言 电磁寻迹小车 之前智能车系列已经做了一
  • 手把手教你OneNET数据可视化

    文章目录 前言OneNET实现数据可视化效果一览发布项目 xff08 5 17更新 xff09 总结 前言 之前介绍了Hi3861使用MQTT协议接入OneNET实现数据的上传以及命令的下发 xff0c 本文主要是介绍一下如何使用OneNE
  • linux---进程间通信(ipc)之管道

    进程间通信方式 管道共享内存消息队列信号量本地套接字等等都能作为我们进程间通信的方法 操作系统提供进程间通信方式的原因 因为对于我们进程来说 xff0c 每一个进程都是相互独立的 xff0c 具有独立性 xff0c 如果我们需要两个不同的进