进程间通信方式-管道

2024-01-09

1. 概述

管道(Pipe)是一种在 Unix/Linux 等操作系统中** 用于进程间通信的机制 **。它可以用于在两个相关的进程之间传递数据,实现简单的数据流通信。管道分为匿名管道和命名管道(FIFO)两种。

管道的本质其实就是 内核中的一块内存(或者叫内核缓冲区) ,这块缓冲区中的数据存储在一个环形队列中,因为管道在内核里边,因此我们不能直接对其进行任何操作。

在这里插入图片描述

管道特点:

  • 管道对应的内核缓冲区大小是固定的,默认为4k(也就是队列最大能存储4k数据)

  • 管道分为两部分:读端和写端(队列的两端),数据从写端进入管道,从读端流出管道。

  • 管道中的数据只能读一次,做一次读操作之后数据也就没有了(读数据相当于出队列)。

  • 管道是单工的:数据只能单向流动, 数据从写端流向读端。

  • 对管道的操作(读、写)默认是阻塞的

    • 读管道:管道中没有数据,读操作被阻塞,当管道中有数据之后阻塞才能解除
    • 写管道:管道被写满了,写数据的操作被阻塞,当管道变为不满的状态,写阻塞解除

读和写都是通过Linux文件IO函数实现的:

// 读管道
ssize_t read(int fd, void *buf, size_t count);
// 写管道的函数
ssize_t write(int fd, const void *buf, size_t count);

原理:

在这里插入图片描述

在上图中假设 父进程通过一系列操作可以通过文件描述符表中的文件描述符fd3写管道,通过fd4读管道 ,然后再**通过 fork() 创建出子进程,那么在父进程中被分配的文件描述符 fd3, fd4也就被拷贝到子进程中,子进程通过 fd3可以将数据写入到内核的管道中,通过fd4将数据从管道中读出来。**也就能够进行数据的通信

2. 匿名管道

匿名管道是一种 只能在相关的进程之间使用的管道 。通常,匿名管道通过 pipe 系统调用创建,其特点包括:

  • 单向通信: 匿名管道是单向的,可以是单向读或单向写。对于双向通信,需要创建两个管道。
  • 进程衍生关系: 通常在创建子进程时,父进程会创建管道,并将其传递给子进程。
  • 阻塞: 如果管道中没有数据可读,读取进程会被阻塞,直到有数据可用。同样,如果管道已满,写入进程会被阻塞,直到有空间可用。
  • 生命周期: 匿名管道在进程间通信结束后自动被关闭,且无法用于无关的进程之间通信。
创建函数
#include <unistd.h>
// 创建一个匿名的管道, 得到两个可用的文件描述符
int pipe(int pipefd[2]);
  • 参数:传出参数,需要传递一个整形数组的地址,数组大小为 2,也就是说最终会传出两个元素

    • pipefd[0]: 对应管道 读端 的文件描述符,通过它可以将数据从管道中读出
    • pipefd[1]: 对应管道 写端 的文件描述符,通过它可以将数据写入到管道中
  • 返回值:成功返回 0,失败返回 -1

以下是一个简单的 C 语言示例,演示了父子进程通过匿名管道进行通信:

#include <stdio.h>
#include <unistd.h>

int main(){
	int pipefd[2];
	char buffer[20];
	
	// 创建管道
	if(pipe(pipefd) == -1){
		perror("pipe");
		return -1;
	}
	
	pid_t pid = fork();
	
	if(pid == -1){
		perror("fork");
		return 1;
	}
	else if(pid == 0) { // 子进程
		// 关闭写入端
		close(pipefd[1]);
		read(pipefd[0], buffer, sizeof(buffer));
		close(pipefd[0]);
		printf("Child Process: Received message - %s\n", buffer);
		
	} else { // 父进程
		close(pipefd[0]); // 关闭读取段
		write(pipefd[1], "Hello, child", 13);
		close(pipefd[1]);
		printf("Parent Process: Sent message\n");
	}
	
	return 0;
}

在这里插入图片描述

3. 有名管道

命名管道是一种在无关的进程之间进行通信的管道,它通过文件系统中的特殊文件来实现。特点包括:

  • 命名: 命名管道有一个关联的文件路径,可以通过文件路径在无关的进程之间进行通信。
  • 阻塞: 与匿名管道类似,命名管道也会在读取端没有数据可读或写入端已满时阻塞。
  • 持久性: 命名管道的生命周期独立于创建进程,需要显式删除。

以下是一个简单的 shell 命令示例,演示了命名管道的使用:

# 创建命名管道
mkfifo myfifo

# 在一个终端中写入数据
echo "Hello, FIFO!" > myfifo

# 在另一个终端中读取数据
cat myfifo

# 删除命名管道
rm myfifo

总的来说,管道是一种简单而有效的进程间通信方式,特别适用于相关进程之间的通信。

4. 管道的读写行为

关于管道不管是有名的还是匿名的,在进行读写的时候,它们表现出的行为是一致的,下面是对其读写行为的总结:

读管道,需要根据写端的状态进行分析:

  • 写端没有关闭 (操作管道写端的文件描述符没有被关闭)
    • 如果管道中没有数据 ==> 读阻塞, 如果管道中被写入了数据, 阻塞解除
    • 如果管道中有数据 ==> 不阻塞,管道中的数据被读完了, 再继续读管道还会阻塞
  • 写端已经关闭了 (没有可用的文件描述符可以写管道了)
    • 管道中没有数据 ==> 读端解除阻塞, read函数返回0
    • 管道中有数据 ==> read先将数据读出, 数据读完之后返回0, 不会阻塞了

写管道,需要根据读端的状态进行分析:

  • 读端没有关闭
    • 如果管道有存储的空间, 一直写数据
    • 如果管道写满了, 写操作就阻塞, 当读端将管道数据读走了, 解除阻塞继续写
  • 读端关闭了,管道破裂(异常), 进程直接退出
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

进程间通信方式-管道 的相关文章

  • numpy 未定义符号:PyFPE_jbuf

    我正在尝试使用一百万首歌曲数据集 为此我必须安装 python 表 numpy cython hdf5 numexpr 等 昨天我设法安装了我需要的所有内容 在使用 hdf5 遇到一些麻烦之后 我下载了预编译的二进制包并将它们保存在我的 b
  • 如何获取 linux 实用程序 tail 的源代码?

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

    使用 OS X 上的框架 我可以使用以下命令将 PNG 复制到粘贴板 在 C 中 显然我可以将 NSPasteboard 与 Cocoa 一起使用 include
  • 构建 makefile 依赖/继承树

    如果我解释得不好或者问了一些明显的问题 我很抱歉 但我是 Linux 内核的新手 而且有点深入 我们有一个嵌入式 Linux 系统 它附带一个 文档非常糟糕的 SDK 其中包含数百个文件夹stuff 大多数文件夹包含rules make m
  • git在Windows和Linux之间切换后强制刷新索引

    我有一个Windows和Linux共享的磁盘分区 格式 NTFS 它包含一个 git 存储库 约 6 7 GB 如果我只使用Windows or 只使用Linux操作 git 存储库一切正常 但是每次切换系统的时候git status命令将
  • 如何在Python中独立于语言安装(linux)获取用户桌面路径

    我找到了 如何找到用户桌面的路径 的几个问题和答案 但在我看来它们都已失效 至少我找到的那些 原因是 如果用户安装的 Linux 不是英语 他或她的桌面很可能位于除 Desktop 例如 对于瑞典语 我相信它是在 Skrivbord 谁知道
  • 从 TypeScript 运行任何 Linux 终端命令?

    有没有办法直接从 TypeScript 类中执行 Linux 终端命令 这个想法是做类似的事情 let myTerminal new LinuxTerminal let terminalResult myTerminal run sudo
  • sleep 0 有特殊含义吗?

    我看到很多用法sleep 0在我的一个客户项目中 代码看起来像这样 while true sleep 0 end 阅读一些像这样的答案this https stackoverflow com questions 3727420 signif
  • 适用于 KDE 和 Gnome 的 Gui [重复]

    这个问题在这里已经有答案了 我想为一个现在是 CLI 的应用程序编写一个 gui 它需要在 KDE 和 Gnome DE 中 看起来不错 充分利用用户的外观设置 如果我选择 Qt 或 GTK 我能够做到这一点吗 它们与两个 DE 集成良好吗
  • 如何在特定 systemd 服务重新启动时触发自定义脚本运行

    我想知道如何安排自定义脚本在重新启动服务时运行 我的用例是 每当重新启动 Tomcat 服务时 我都必须运行多个命令 我想知道是否有一种方法可以编写脚本并安排它在重新启动 Tomcat 服务时运行 我已将 tomcat 脚本设置为 syst
  • 在主目录中安装库

    在 Linux Ubuntu 中 我尝试运行一个工具 但它显示错误 库丢失 我无权在系统中安装任何内容 或者根本无法从我的用户帐户执行 sudo 是否可以在我的主目录 没有 sudo 中安装缺少的库 在我的例子中为 libstdc so 6
  • 信号处理程序有单独的堆栈吗?

    信号处理程序是否有单独的堆栈 就像每个线程都有单独的堆栈一样 这是在 Linux C 环境中 来自 Linux 手册页signal 7 http kernel org doc man pages online pages man7 sign
  • PHP 致命错误:未找到“MongoClient”类

    我有一个使用 Apache 的网站 代码如下 当我尝试访问它时 我在 error log 中收到错误 PHP Fatal Error Class MongoClient not found 以下是可能错误的设置 但我认为没有错误 php i
  • 如何更改 Ubuntu 14.04 上的 php-cli 版本?

    我是 Linux 新手 在篡改时破坏了一些 php 设置 如果我执行一个包含以下内容的 php 脚本 phpinfo 它显示 php 版本为 5 6 但通过命令行 如果我运行php v它返回 7 0 版本 我想让两个版本匹配 我怎样才能修复
  • 嵌入式Linux poll()不断返回

    我有一个特别的问题 当我知道没有什么可读时 民意调查不断返回 因此设置如下 我有 2 个文件描述符 它们构成fd设置民意调查监视 一种用于引脚从高到低的变化 GPIO 另一个用于代理输入 代理输入出现问题 处理的顺序是 启动main函数 然
  • ansible 重新启动 2.1.1.0 失败

    我一直在尝试创建一个非常简单的 Ansible 剧本 它将重新启动服务器并等待它回来 我过去在 Ansible 1 9 上有一个可以运行的 但我最近升级到 2 1 1 0 并且失败了 我正在重新启动的主机名为 idm IP 为 192 16
  • Locale.getDefault() 始终返回 en

    unix 机器上的服务器始终使用 en 作为默认区域设置 以下是区域设置输出 LANG en US LC CTYPE C LC NUMERIC C LC TIME C LC COLLATE C LC MONETARY C LC MESSAG
  • 何时使用 pthread 条件变量?

    线程问题 看来 只有在其他线程调用 pthread cond notify 之前调用 pthread cond wait 时 条件变量才起作用 如果在等待之前发生通知 那么等待将被卡住 我的问题是 什么时候应该使用条件变量 调度程序可以抢占
  • 使用 find - 删除除任何一个之外的所有文件/目录(在 Linux 中)

    如果我们想删除我们使用的所有文件和目录 rm rf 但是 如果我希望一次性删除除一个特定文件之外的所有文件和目录怎么办 有什么命令可以做到这一点吗 rm rf 可以轻松地一次性删除 甚至可以删除我最喜欢的文件 目录 提前致谢 find ht
  • 无法加载 JavaHL 库。- linux/eclipse

    在尝试安装 Subversion 插件时 当 Eclipse 启动时出现此错误 Failed to load JavaHL Library These are the errors that were encountered no libs

随机推荐

  • jquery的contains如何实现精准匹配

    HTML结构
  • Android studio SeekBar应用设计

    一 xml布局文件 1 默认状态的
  • AIDL通信过程中设置死亡代理

    概述 在进行进程间通信的过程中 如何服务端进程由于某种原因异常终止 我们的远程调用就会失败 影响我们的功能 那么怎么样能够知道服务端进程是否终止了呢 那就是给Binder设置死亡代理 下面看看如何设置 Override public voi
  • 小学二三年级入门信奥赛,如何从Scratch进入C++的学习

    小学生几年级适宜开始学习C 这是讨论的比较热烈 也是比较热门的话题 小学生适宜几年级开始学C 小学生适宜几年级开始学C CSDN博客 simple happiness 信息学规划 北京二年级学生图形化过二级想往信奥靠拢如何准备 信息学规划
  • Prometheus Blackbox_exporter笔记

    一 安装Promtheus 在 Prometheus 官网 Download Prometheus 获取适用于 Linux 的 Prometheus 安 装包 这里我选择最新的 2 46 0 版本 我是 Linux 系统 选择下载 prom
  • AIDL通信过程中设置死亡代理

    关于AIDL的使用参考学习 https blog csdn net u011240877 article details 72765136 https blog csdn net iromkoear article details 5970
  • qemu调用spice库添加memslot

    1 qemu中的spice display c添加memslot void qemu spice add memslot SimpleSpiceDisplay ssd QXLDevMemSlot memslot qxl async io a
  • 合肥一食品仓库发生火灾,富维图像仓库火灾识别避免财产损失

    2024年1月5日 安徽合肥一家食品仓库不幸遭遇了火灾 11时50分左右 浓烟滚滚 火光冲天 令人心惊肉跳 幸运的是 没有造成人员伤亡 但仓库内大量物资被烧毁 财产损失巨大 此次事件再次提醒我们 火灾防护的重要性不容忽视 而在这方面 北京富
  • 机器配音解说可以用什么软件弄?我来告诉你

    大家每一天工作时都要长时间接触电子屏幕 下班回家之后 小说吸引力是不是不如从前了 别急着让喜欢的作者 背锅 我想 你们之所以 收藏从未停止 阅读从未开始 也有一部分原因是眼睛累了 所以自然就会觉得小说不好看 不过 难道打工人就无法全身心地沉
  • filezilla中文目录乱码怎么解决

    FileZilla是一款常用的文件传输工具 但在使用过程中可能会遇到乱码的问题 以下是一些可能的解决方案 设置字符集 在连接上站点后 点击菜单栏的 文件 选项 下拉选择 添加当前连接到站点管理器 在弹出的 站点管理器 窗口中 左侧选择 新站
  • 如何防护零日攻击

    零日攻击是什么 零日攻击 也称为零时差攻击 通常是指利用还没有被补丁的安全漏洞进行的攻击 这些漏洞在被发现后 由于各种原因 软件供应商未能及时发布补丁 使得黑客有机会利用这些漏洞进行攻击 零日攻击通常由技术高超的黑客发起 他们在对目标系统或
  • 光纤知识总结

    1光纤概念 光导纤维 英语 Optical fiber 简称 光纤 是一种由玻璃或塑料制成的纤维 利用光在这些纤维中以全内 反射 原理传输的光传导工具 微细的光纤封装在塑料护套中 使得它能够弯曲而不至于断裂 通常光纤的一端的发射设备使用发光
  • 第八章 确认访问用户身份的认证

    第八章 确认访问用户身份的认证 8 1 何为认证 在计算机安全和网络通信的背景下 认证是 确认实体 如用户 计算机系统 服务 身份真实性的过程 认证是确保系统只对合法用户或实体开放访问权限的一种关键机制 在网络通信中 认证通常涉及验证用户或
  • GIT 命令

    记录用到的有用的git 命令 git diff gt a diff 产生diff文件 到目的端相同目录下赋值a diff然后执行 git apply a diff
  • 山西电力市场日前价格预测【2024-01-09】

    日前价格预测 预测说明 如上图所示 预测明日 2024 01 09 山西电力市场全天平均日前电价为314 92元 MWh 其中 最高日前电价为593 66元 MWh 预计出现在18 15 最低日前电价为54 95元 MWh 预计出现在13
  • 网络协议与攻击模拟_01winshark工具简介

    一 TCP IP协议簇 网络接口层 没有特定的协议 物理层 PPPOE宽带拨号 应用场景 宽带拨号 运营商切网过来没有固定IP就需要拨号 家庭带宽一般都采用的是拨号方式 数据链路层 网络层 IP v4 v6 ARP 地址解析协议 RARP
  • Linux ls命令

    目录 一 配置项 1 1 ls l 1 2 ls a 1 3 ls lrt 1 4 ls ld 二 案例 2 1 查看指定文件夹下文件的数量
  • ERROR 5025 (HY000): Insert has filtered data in strict mode, tracking_url=http://IP

    通过http api批量插入数据的时候报Reason null value for not null column column xxx src line 解决方法 检查是否有null值存在 增加数据库字段长度 如下语句更改长度 ALTER
  • 【工作日语】一

    連続詞 主観想方 中国語 因為 所以 例 仕様理解 大変 提出 訳文 仕様很難理解 能否 向我方 提供流程図 客観存在 中国語 因為 所以 例 今回 案件 出力全 西暦 和暦 場合 西暦 変更 下 訳文 因为本次案件都是输出的公历 和历的地
  • 进程间通信方式-管道

    1 概述 管道 Pipe 是一种在 Unix Linux 等操作系统中 用于进程间通信的机制 它可以用于在两个相关的进程之间传递数据 实现简单的数据流通信 管道分为匿名管道和命名管道 FIFO 两种 管道的本质其实就是 内核中的一块内存 或