Linux:管道文件及相关API

目录

  • 前言
  • 一、管道文件
    • 1、基本概念
    • 2、匿名(无名)管道
    • 3、命名(有名)管道
    • 4、管道的特点
    • 5、思考:何时只能使用无名管道,何时又只能用有名管道?
      • 无名管道(匿名管道)适用的情况:
      • 有名管道(命名管道)适用的情况:
  • 二、相关API介绍
    • 1. `int pipe(int pipefd[2])`
    • 2. `int mkfifo(const char *pathname, mode_t mode)`
    • 3. `int open(const char *pathname, int flags)`
    • 4. `ssize_t read(int fd, void *buf, size_t count)`
    • 5. `ssize_t write(int fd, const void *buf, size_t count)`
    • 6、示例代码
  • 四、参考阅读

前言

  在 Linux 系统中,管道是一种非常常用的进程间通信机制,它简单、高效,并且易于使用。本文将深入介绍 Linux 管道的原理、分类、特点以及使用方法,帮助读者更好地理解和应用管道在系统编程中的重要性。

一、管道文件

1、基本概念

  在 Linux 中,管道文件(Pipeline)是一种特殊的文件类型,用于在进程之间进行通信。管道文件被用来将一个进程的标准输出和另一个进程的标准输入连接起来,实现这两个进程之间的数据传输。管道文件有两种类型:匿名管道命名管道

2、匿名(无名)管道

  匿名管道是最常见的一种管道,通过命令行中的竖线符号 | 创建。例如:command1 | command2,这样可以将 command1 的输出直接传递给 command2 的输入。匿名管道只存在于相关进程的生命周期内,进程结束后管道也会自动关闭。

  • 特点:

    • 单向通信,数据从一个进程流向另一个进程。
    • 临时性,只在相关进程生命周期内存在。
    • 通常用于连接两个相关进程,例如 command1 | command2。
  • 使用注意事项:

    • 一次性的,一旦相关进程结束,管道就会关闭,数据会丢失。
    • 只能用于相关进程之间的通信,不能用于不相关进程之间的通信。

  在 Linux 中,可以使用一些常见的命令来演示匿名管道的使用,以实现进程之间的数据传输。以下是一个简单的示例,使用 ls 命令列出当前目录下的文件和子目录,然后使用 grep 命令过滤出包含特定字符的结果。

ls | grep "txt"

  在这个示例中,ls 命令列出当前目录下的文件和子目录的信息,并将结果通过匿名管道传递给 grep 命令。grep 命令会过滤出包含 “txt” 字符串的结果,然后将结果输出到标准输出。这样就实现了通过匿名管道连接两个命令,实现数据传输和处理的功能。

  你可以尝试在终端中执行上述命令,查看输出结果。这种使用匿名管道的方式可以帮助简化多个命令之间的数据传递和处理,提高系统管理和脚本编写的效率。当然,除了 lsgrep,你还可以结合其他命令来展示匿名管道的强大功能和灵活性。

3、命名(有名)管道

  命名管道也称为 FIFO(First In, First Out),它是一种特殊类型的文件,通过 mkfifo 命令创建。命名管道可以持久存在于文件系统中,并允许不相关的进程之间进行通信。命名管道通过文件系统中的路径名进行访问,进程可以像访问普通文件一样读写数据。

  • 特点:

    • 单向或双向通信,可持久存在于文件系统中,多个进程之间进行通信。
    • 可用于不相关进程之间的通信。
    • 通过 mkfifo 命令创建。
  • 使用注意事项:

    • 需要注意文件权限和文件系统容量问题。
    • 小心处理管道阻塞的情况,避免死锁问题。

创建命名管道的步骤如下:

  • 使用 mkfifo 命令创建命名管道文件:mkfifo pipe_file
  • 使用不同的进程分别打开该管道文件进行读写操作

  命名管道通常用于需要持久存在的进程通信,比如两个独立的进程之间需要进行数据交换,但又不需要建立像 TCP/IP 连接那样的网络通信。

4、管道的特点

  1. 单向通信: 管道是一种单向通信方式,数据从一个进程流向另一个进程。在匿名管道中,数据只能从管道的写入端流向读取端;在命名管道中,数据也是单向传输的,但可以支持双向通信(半双工)。

  2. 进程之间通信: 管道主要用于实现进程之间的通信,通过将一个进程的标准输出重定向到管道,另一个进程的标准输入重定向到同一管道,实现数据的传递。

  3. 数据流传输: 管道是一种数据流传输方式,数据以流的形式从一个进程传输到另一个进程,适合于需要连续处理数据的场景。

  4. 临时性: 匿名管道是临时的,只存在于相关进程的生命周期内(一般用于父子进程);而命名管道是持久的,可以在文件系统中保留,允许不相关的进程之间进行通信。

  5. 有限缓冲: 管道的数据传输有限制缓冲区大小,当缓冲区满时,写入端会被阻塞,直到读端读取数据,释放缓冲区空间。

  6. 阻塞式通信: 当管道中没有数据可读时,读取进程会被阻塞;当管道满时,写入进程也会被阻塞,直到有空间写入数据。

  7. 操作简便: 通过管道可以快速简便地实现进程间的数据传输,无需繁琐的网络连接设置或文件读写操作。

  8. 常用于进程调用链: 管道经常用于构建进程调用链,将多个命令通过管道连接起来,实现复杂任务的处理。

  总的来说,管道是 Linux 系统中非常实用的进程间通信机制,具有简单、高效、快速的特点,适用于一些需要实时数据传输并且不需要长期存储的场景。通过合理地使用管道,可以有效提升进程之间的通信效率和数据处理能力。

5、思考:何时只能使用无名管道,何时又只能用有名管道?

无名管道(匿名管道)适用的情况:

  1. 用于父子进程通信: 无名管道通常用于在父子进程之间进行通信,因为无名管道是一种特殊的文件描述符,只能用于有亲缘关系的进程之间通信。
  2. 单向通信: 无名管道是单向的,只能在一个方向上传输数据,通常用于实现单向数据传输的场景,比如父进程向子进程传输数据。
  3. 临时传输数据: 无名管道通常被用作临时通道,进程间传输少量数据,常用于将一个命令的输出传递给另一个命令进行处理。

有名管道(命名管道)适用的情况:

  1. 用于任意进程间通信: 有名管道不仅可以用于有亲缘关系的进程通信,还可以用于任意进程间通信,只要它们可以访问同一个管道文件。
  2. 双向通信: 有名管道支持双向通信,进程可以通过同一个管道文件来实现双向数据传输。
  3. 永久传输数据: 有名管道创建后会生成一个文件节点,直到被明确删除前一直存在,因此适用于需要长期或者反复传输数据的场景。

综上所述,无名管道适合用于父子进程之间的单向临时通信,有名管道则适合用于任意进程之间的双向永久通信。根据具体的需求和场景选择合适的管道类型可以更有效地实现进程间的数据交换和通信。

二、相关API介绍

  在 Linux 系统中,管道文件相关的 API 主要包括 pipe()mkfifo()open()read()write() 等函数。以下是这些 API 的详细解释:

1. int pipe(int pipefd[2])

  • 功能: 创建一个匿名管道,并返回两个文件描述符,pipefd[0] 用于读取数据,pipefd[1] 用于写入数据。
  • 参数: pipefd 是一个整型数组,用于存放管道的文件描述符。
  • 返回值: 若成功,返回 0;若失败,返回 -1。
  • 示例:
    int fd[2];
    if (pipe(fd) == -1) {perror("pipe");exit(EXIT_FAILURE);
    }
    

2. int mkfifo(const char *pathname, mode_t mode)

  • 功能: 创建一个命名管道(FIFO)。
  • 参数:
    • pathname 是要创建的命名管道的路径名。
    • mode 是文件的权限模式。
  • 返回值: 若成功,返回 0;若失败,返回 -1。
  • 示例:
    if (mkfifo("/tmp/myfifo", 0666) == -1) {perror("mkfifo");exit(EXIT_FAILURE);
    }
    

3. int open(const char *pathname, int flags)

  • 功能: 打开一个管道文件,返回文件描述符。
  • 参数:
    • pathname 是要打开的管道文件的路径名。
    • flags 指定打开文件的方式,如 O_RDONLY(只读)和 O_WRONLY(只写)。
  • 返回值: 若成功,返回一个新的文件描述符;若失败,返回 -1。
  • 示例:
    int fd = open("/tmp/myfifo", O_WRONLY);
    if (fd == -1) {perror("open");exit(EXIT_FAILURE);
    }
    

4. ssize_t read(int fd, void *buf, size_t count)

  • 功能: 从管道文件中读取数据。
  • 参数:
    • fd 是管道文件的文件描述符。
    • buf 是用于存放读取数据的缓冲区。
    • count 是要读取的字节数。
  • 返回值: 若成功,返回实际读取的字节数;若到达文件末尾,返回 0;若失败,返回 -1。
  • 示例:
    char buffer[100];
    ssize_t bytes_read = read(fd, buffer, sizeof(buffer));
    

5. ssize_t write(int fd, const void *buf, size_t count)

  • 功能: 向管道文件中写入数据。
  • 参数:
    • fd 是管道文件的文件描述符。
    • buf 是要写入的数据。
    • count 是要写入的字节数。
  • 返回值: 若成功,返回实际写入的字节数;若失败,返回 -1。
  • 示例:
    char *msg = "Hello, world!";
    ssize_t bytes_written = write(fd, msg, strlen(msg));
    

  以上是使用管道文件相关 API 的基本介绡,开发者在创建、打开、读写管道文件时可以结合这些函数来完成必要的操作。在实际编程过程中,需要注意处理错误情况,确保程序的稳定性和可靠性。

6、示例代码

以下是一个简单的示例代码,展示如何在两个进程之间使用管道文件进行通信。首先创建一个命名管道文件,然后通过 fork() 创建子进程,父进程向管道中写入数据,子进程从管道中读取数据,并打印输出。具体代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>#define FIFO_PATH "/tmp/myfifo"int main() {// 创建命名管道文件if (mkfifo(FIFO_PATH, 0666) == -1) {perror("mkfifo");exit(EXIT_FAILURE);}pid_t pid = fork();if (pid == -1) {perror("fork");exit(EXIT_FAILURE);}if (pid > 0) {// 父进程写入数据到管道int fd = open(FIFO_PATH, O_WRONLY);if (fd == -1) {perror("open");exit(EXIT_FAILURE);}char *msg = "Hello, child process!";if (write(fd, msg, strlen(msg)) == -1) {perror("write");exit(EXIT_FAILURE);}close(fd);} else if (pid == 0) {// 子进程从管道读取数据int fd = open(FIFO_PATH, O_RDONLY);if (fd == -1) {perror("open");exit(EXIT_FAILURE);}char buffer[100];ssize_t bytes_read = read(fd, buffer, sizeof(buffer));if (bytes_read == -1) {perror("read");exit(EXIT_FAILURE);}buffer[bytes_read] = '\0';  // 添加字符串结束符printf("Child process received: %s\n", buffer);close(fd);}return 0;
}

  在此示例中,父进程向管道文件写入字符串 “Hello, child process!”,子进程从管道文件读取数据并打印输出。这样就实现了父子进程之间的简单通信。在实际使用中,可以根据需求修改数据传输方式和内容,以满足不同场景下的进程间通信需求。

四、参考阅读

  初识linux之管道
  Linux——进程间通信——管道(文件)通信
  linux之《管道》

  欢迎大家指导和交流!如果我有任何错误或遗漏,请立即指正,我愿意学习改进。期待与大家一起进步!

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

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

相关文章

2024最新AI系统ChatGPT网站源码, AI绘画系统

一、前言说明 R5Ai创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支持GP…

CVE-2024-23334 AIOHTTP 目录遍历漏洞分析

漏洞描述&#xff1a; aiohttp 是一个用于 asyncio 和 Python 的异步 HTTP 客户端/服务器框架。使用aiohttp作为Web服务器并配置静态路由时&#xff0c;需要指定静态文件的根路径。此外&#xff0c;选项“follow_symlinks”可用于确定是否遵循静态根目录之外的符号链接。当“f…

css样式元素的相对定位,绝对定位,固定定位等元素定位运用技巧详解

文章目录 1.相对定位 relative2.绝对定位 absolute3.固定定位4.display 转换元素5.float浮动6.float产生内容塌陷问题7.overflow CSS样式学习宝典&#xff0c;关注点赞加收藏&#xff0c;防止迷路哦 在CSS中关于定位的内容是&#xff1a;position:relative | absolute | static…

Unreal触屏和鼠标控制旋转冲突问题

Unreal触屏和鼠标控制旋转冲突问题 鼠标控制摄像机旋转添加Input轴计算旋转角度通过轴事件控制旋转 问题和原因问题原因 解决办法增加触摸控制旋转代码触屏操作下屏蔽鼠标轴响应事件 鼠标控制摄像机旋转 通过Mouse X和Mouse Y控制摄像机旋转。 添加Input轴 计算旋转角度 通过…

SpringBootWeb快速入门

1.创建springboot工程&#xff0c;新建module 2.勾选web开发相关依赖 3.删除多余文件 4.新建类 5.启动类中运行main方法 6.启动 默认端口号8080 7.打开浏览器&#xff0c;地址栏输入 8.报错 9.原因&#xff0c;控制层位置放错&#xff0c;剪切controller层放进com.example …

[vue error] TypeError: Components is not a function

问题详情 问题描述: element plus按需导入后&#xff0c;启动项目报错&#xff1a; 问题原因 unplugin-vue-components插件版本问题 查看 unplugin-vue-components插件可以发现版本太高了 问题解决 unplugin-vue-components 版本高了&#xff0c;我用的0.26.0&#xff0c…

AI写的wordpress网站首页模板 你觉得怎么样?

以下是一个AI写的基本的首页模板示例&#xff0c;包含您提到的各个模块。请注意&#xff0c;这只是一个基本框架&#xff0c;您可能需要根据您的具体需求进行进一步的定制和调整。 <!DOCTYPE html> <html <?php language_attributes(); ?>> <head>&…

【STM32+HAL】姿态传感器陀螺仪MPU6050模块

一、准备工作 有关OLED屏初始化的问题&#xff0c;详见【STM32HAL】OLED显示初始化配置 二、所用工具 1、芯片&#xff1a;STM32F10C8T6 2、CUBEMX配置软件 3、 6 轴运动处理组件MPU6050 三、实现功能 OLED屏显示姿态角 四、HAL配置步骤 1、开启I2C1进行MPU6050通信 2、开…

供应链管理(SCM):界面设计全面扫盲,得供应链者得天下

大家伙&#xff0c;我是大千UI工场&#xff0c;专注UI分享和项目接单&#xff0c;本期带来供应链系统的设计分享&#xff0c;欢迎大家关注、互动交流。 一、什么是SCM SCM系统是供应链管理&#xff08;Supply Chain Management&#xff09;系统的缩写。供应链管理是指协调和管…

计算机视觉 了解OpenCV、COLMAP、PyTorch3D 和 OpenGL 中坐标系3D转换的简要指南

一、简述 由于坐标系不同,在OpenCV、COLMAP、PyTorch3D和OpenGL等 3D 框架的世界中进行转换可能会令人觉得头疼。这里比较它们的坐标系并提供它们之间转换的示例。核心还是找到在这些不同的 3D 环境中无缝工作所需的知识,让我们以清晰直接的方式探索和理解这些坐标系。 2D 成…

【笔记版】edgecore.yaml分析总结

1. 文件路径 /etc/kubeedge/config edgecore.yaml是该目录下唯一的文件 附上链接&#xff1a;edgecore.yaml 2. 文件生成方式 2.1 方式一 使用keadm安装部署的方式&#xff0c;执行完keadm join --cloudcore-ipportcloudcore监听的IP地址:端口&#xff08;默认为10002&…

题目 1431: 蓝桥杯第五届真题-分糖果

题目描述: 有n个小朋友围坐成一圈。老师给每个小朋友随机发偶数个糖果&#xff0c;然后进行下面的游戏&#xff1a; 每个小朋友都把自己的糖果分一半给左手边的孩子。 一轮分糖后&#xff0c;拥有奇数颗糖的孩子由老师补给1个糖果&#xff0c;从而变成偶数。 反复进行这个游戏…

设计模式精解:GoF 23种设计模式全解析

在软件工程中&#xff0c;设计模式是为了解决常见的软件设计问题而形成的一套经典解决方案。这些模式不仅能够帮助开发者提高设计的灵活性和代码的重用性&#xff0c;还能使问题的解决方案更加清晰、易于理解。《设计模式精解&#xff0d;GoF 23种设计模式》一书中所列举的23种…

微信小程序的单位

在小程序开发中&#xff0c;rpx是一种相对长度单位&#xff0c;用于在不同设备上实现自适应布局。它是微信小程序特有的单位&#xff0c;表示屏幕宽度的 1/750。 rpx单位的好处在于可以根据设备的屏幕宽度进行自动换算&#xff0c;使得页面在不同设备上保持一致的显示效果。例…

学习笔记 前端

学习笔记 前端 学习记录nodejsyarn解决方法 学习记录 nodejs yarn 描述&#xff1a;想体验一下chatgptnextweb在本地部署&#xff0c;但是本地部署需要yarn环境&#xff0c;网上看了yarn在node16以上就自带了&#xff0c;而我的电脑是node18&#xff0c;所以就直接输入了ya…

(十)SpringCloud系列——openfeign的高级特性实战内容介绍

前言 本节内容主要介绍一下SpringCloud组件中微服务调用组件openfeign的一些高级特性的用法以及一些常用的开发配置&#xff0c;如openfeign的超时控制配置、openfeign的重试机制配置、openfeign集成高级的http客户端、openfeign的请求与响应压缩功能&#xff0c;以及如何开启…

论文阅读-高效构建检查点

论文标题&#xff1a;On Efficient Constructions of Checkpoints 摘要 高效构建检查点/快照是训练和诊断深度学习模型的关键工具。在本文中&#xff0c;我们提出了一种适用于检查点构建的有损压缩方案&#xff08;称为LC-Checkpoint&#xff09;。LC-Checkpoint同时最大化了…

MFC中CString的MakeUpper使用方法

在MFC中&#xff0c;CString类提供了MakeUpper函数来将字符串中的字符全部转换为大写。MakeUpper函数没有参数&#xff0c;它会直接修改原始的CString对象。 下面是一些示例代码&#xff0c;演示了如何使用MakeUpper函数&#xff1a; CString str "Hello, World!"…

uniapp开发android原生插件

一、下载原生开发SDK Android 离线SDK - 正式版 | uni小程序SDK (dcloud.net.cn)、 https://nativesupport.dcloud.net.cn/AppDocs/download/android.html 将开发uniappa原生android的插件解压到ben本地目录&#xff0c;目录结构如下&#xff1a; 接下就可以使用 UniPlugin-Hel…

【本科组冠名奖】2023年第八届数维杯数学建模挑战赛获奖感言

美国大学生数学建模竞赛已结束过半&#xff0c;现在又迎来了2024年第九届数维杯国赛&#xff0c;准备参加今年数维杯国赛的同学&#xff0c;今天我们一起看看去年优秀的选手都有什么获奖感言吧~希望能帮到更多热爱数学建模的同学。据说文末在看点赞的大佬都会直冲国奖呢&#x…