首页 > 系统相关 >Linux下使用pipe进行父子进程间通信

Linux下使用pipe进行父子进程间通信

时间:2024-09-15 11:51:31浏览次数:3  
标签:pipe 创建 pipefd 间通信 管道 Linux 进程 读端

引入

之前我们介绍了多进程以及创建进程的函数fork,下面我们将继续深入,讨论一下多进程间的通信问题;

pipe 管道

谈论多进程通信,就离不开pipe(管道),这是一个系统调用,用于在 UNIX 和类 UNIX 系统(如 Linux)上创建一个管道(pipe),实现进程间通信。它创建了一个双向的通信通道,允许一个进程向另一个进程发送数据。管道是单向的,即数据只能沿一个方向流动:从读端读取数据,从写端写入数据。 所以我们需要分别关闭管道两端的读取端和写入端,使得进程间信息可以单向传输;

函数定义

int pipe(int pipefd[2]);
  • 参数:
    • pipefd[2]:一个包含两个整数的数组,用来保存两个文件描述符(file descriptor):
      • pipefd[0] 是管道的读端(用于读取数据);
      • pipefd[1] 是管道的写端(用于写入数据);
  • 返回值:
    • 成功时返回0:表示管道创建成功;
    • 失败时返回-1:并设置errno表示

工作原理

pipe() 系统调用创建一个可以在进程之间传递数据的管道,它会生成两个文件描述符:

  • pipefd[0]:用于从管道的读端读取数据。
  • pipefd[1]:用于向管道的写端写入数据。

在典型的使用场景中:

  • 父进程可以创建一个管道,然后使用 fork() 创建子进程。
  • 子进程可以关闭管道的写端,通过读端读取父进程发送的数据。
  • 父进程可以关闭管道的读端,通过写端向子进程发送数据。

管道是一个单向的通信通道,因此数据只能从写端发送到读端。如果想要双向通信,需要创建两个管道,一个用于从父进程到子进程,另一个用于从子进程到父进程; 下面是示例代码:

#include <iostream>
#include <unistd.h>
#include <cassert>

int main() {
    int pipefd[2];  // 保存管道的读端和写端
    char buffer[100];

    // 创建管道
    if (pipe(pipefd) == -1) {
        perror("pipe failed");
        return 1;
    }

    // 创建子进程
    pid_t pid = fork();
    assert(pid >= 0);

    if (pid == 0) {  // 子进程
        close(pipefd[1]);  // 关闭写端
        // 从管道读端读取数据
        read(pipefd[0], buffer, sizeof(buffer));
        std::cout << "子进程读取到的消息: " << buffer << std::endl;
        close(pipefd[0]);
    } else {  // 父进程
        close(pipefd[0]);  // 关闭读端
        const char* message = "Hello from parent!";
        // 向管道写端写入数据
        write(pipefd[1], message, strlen(message) + 1);
        close(pipefd[1]);
    }

    return 0;
}

解释

  • 父进程创建了一个管道,通过 pipefd[0] 和 pipefd[1] 分别代表管道的读端和写端。
  • 父进程使用 fork() 创建子进程,子进程会继承父进程的文件描述符。
  • 在子进程中,关闭写端,然后通过管道的读端 pipefd[0] 读取父进程写入的数据。
  • 在父进程中,关闭读端,然后通过管道的写端 pipefd[1] 写入一条消息。

常见问题

  1. 单向通信: 管道的一个限制是它只能进行单向通信。如果需要双向通信,可以使用两个管道,或者使用其他更复杂的 IPC(进程间通信)机制,如套接字、共享内存等。

  2. 管道阻塞:

  • 如果管道的写端没有被关闭,读操作可能会被阻塞,直到有数据可供读取。
  • 同样,如果管道的读端没有被关闭,写操作可能会阻塞,直到缓冲区有空间来写数据。
  1. 关闭文件描述符: 在父子进程中使用管道时,确保正确关闭不需要的文件描述符。例如,父进程应该关闭读端,而子进程应该关闭写端。否则,管道通信可能会出现错误。

管道的应用场景

  1. 进程间通信: 管道最常见的用途是实现父子进程之间的简单数据通信,尤其是在 fork() 之后。

  2. 子进程的输出重定向: 管道可以用于将子进程的标准输出重定向到父进程,以便父进程读取子进程的输出。

  3. 流水线处理: 在命令行中,使用管道 | 实现将一个程序的输出传递给另一个程序,正是基于 pipe() 的概念。例如:

ls | grep *.cpp
# 将ls的输出通过管道传递给 grep 进行过滤

注意,上述谈论的管道主要是匿名管道,与之对应的还有命名管道,这里不做深究,下一篇文章可以详细讲解一下二者之间的区别;

代码框架

有了上述的pipe管道函数的介绍,我们就可以编写一个用于测试父子进程间通信的程序,接下来我们将分析这个程序的主要功能及其实现方法,搭建出一个简易的框架:

  1. 首先我们需要一串父子进程,用于传输和接收信息,可以使用fork函数进行创建,同时还需要储存相应进程的信息,方便我们进行操作;
  2. 此外,我们还需要一个传输函数和接收函数,用于父进程发送信息和子进程接收信息;
  3. 同时,我们还需要一个待处理任务组,用于子进程处理相关的任务,这里为了简化操作,我们将采用简单的示例代码,只是为了检测相应的功能;
  4. 关于我们传递的信息内容,我们需要传递执行任务的子进程编号以及执行的任务编号,以便于子进程可以实现负载均衡image.png

代码实现

完成了上述的准备工作,我们就可以着手代码实现了,关于代码中的细节问题,注释中都有相应的解释,我后续也会再去完善相应的注释解释工作,代码具体见于我的GitHub仓库,实现代码在pipe分支

标签:pipe,创建,pipefd,间通信,管道,Linux,进程,读端
From: https://blog.51cto.com/u_16271511/12023713

相关文章

  • 4.linux重定向和管道
    目录 一.重定向1.FD2.重定向案例><2.1输出>2.2输入<3.扩展二.管道1.管道|1.1进程管道Piping1.2tee管道2.参数传递Xargs 一.重定向 #touchtime#date>time.txt//>将本身输出到屏幕的东西给他弄到time文件中 1.FD-----标准输入、标准输......
  • linux 操作系统下的compress命令介绍和使用案例
    linux操作系统下的compress命令介绍和使用案例compress命令是Linux系统中用于文件压缩的一个工具,主要使用Lempel-Ziv-Welch(LZW)算法进行数据压缩。压缩后,文件的扩展名将变为“.Z”。虽然compress命令在历史上有其重要性,但在现代Linux系统中,它已经被更高效的压缩工具如gzip......
  • linux 操作系统下cp命令介绍及案例应用
    linux操作系统下cp命令介绍及案例应用cp命令是Linux操作系统中用于复制文件和目录的基本命令。它的功能强大,适用于各种文件管理任务cp命令概述基本语法:bashcp[options]<source><destination>功能:复制单个文件或多个文件到指定位置。递归复制目录及其内容。选项可......
  • Linux内存管理方式
    Linux内存管理涉及到多个方面,包括物理内存的分配和回收、虚拟内存的管理、页面置换、内存保护等。以下是Linux内存管理的主要方式和机制:1.虚拟内存(VirtualMemory)虚拟地址空间:每个进程拥有自己的虚拟地址空间,虚拟地址空间与物理内存是分开的。进程在运行时使用虚拟地......
  • 1Panel:一个现代化、开源的 Linux 服务器运维管理面板
    前言之前有小伙伴问:Linux服务器运维管理除了宝塔,还有其他值得推荐的管理软件吗?,今天大姚给大家分享一个现代化、开源的Linux服务器运维管理面板:1Panel。项目介绍1Panel是新一代的Linux服务器运维管理面板,旨在通过现代化的Web界面帮助用户轻松管理Linux服务器。该项目是开......
  • 1Panel:一个现代化、开源的 Linux 服务器运维管理面板
    前言之前有小伙伴问:Linux服务器运维管理除了宝塔,还有其他值得推荐的管理软件吗?,今天大姚给大家分享一个现代化、开源的Linux服务器运维管理面板:1Panel。项目介绍1Panel是新一代的Linux服务器运维管理面板,旨在通过现代化的Web界面帮助用户轻松管理Linux服务器。该项目......
  • 3.linux进程管理
    目录一.进程管理1.进程概念2.进程生命周期和状态3.进程管理process3.1ps-静态查看进程3.2 top-动态查看进程3.3.使用信号控制进程3.4nice-优先级二.作业控制jobs三.虚拟文件系统proc四.线程(可看可不看)1.状态2.调度算法3.通信方式4.线程和进程的区别5.线......
  • USB总线-Linux内核USB3.0 Hub驱动分析(十四)
    1.概述USBHub提供了连接USB主机和USB设备的电气接口。USBHub拥有一个上行口,至少一个下行口,上行口连接上一级的Hub的下行口或者USB主机,连接主机的为RootHub,下行口连接下一级Hub的上行口或者USB设备。经过Hub的扩展,一个USB主机可以和多个USB设备通信。USBHub有如下特性:良好的......
  • Linux相关命令的使用
    一、压缩和归档的命令1.1压缩和解压缩操作对象是单个文件压缩方式:gzip--->.gzbzip--->.bz2xz--->.xz上是三种压缩方式:压缩率依次递减,压缩速率依次递减。gzipfile//将文件file按gzip格式进行压缩//压缩之后原文件就不存在了,只留下名为file.gz的压缩后......
  • Linux相关命令及shell命令
    一、链接文件1.1软链接(符号链接)ls-l能看到类型为链接文件的都是软连接软连接类似于windows的快捷方式创建软连接的方式:ln-s被链接的文件文件名要生成的文件名注意:1.我们一般创建软连接时最好使用绝对路径否则一旦相对位置发生变化链接就会失效。2.如果被链......