Linux系统编程之无名管道

news/2025/2/23 4:29:40

概述

        在Linux系统中,无名管道是一种简单的进程间通信机制。它允许一个进程创建一对文件描述符,其中一个用于读取,另一个用于写入。当一个进程通过系统调用创建了一个无名管道后,便可以将这两个文件描述符传递给它的子进程,使得父子进程之间可以进行单向的数据交换。

无名管道的特点

        无名管道的使用相对比较简单,具有以下一些显著的特点。

        1、半双工。无名管道是单向的,意味着我们不能同时从同一个管道两端既读又写。

        2、有限容量。无名管道有一个固定的缓冲区大小,默认情况下通常是64KB左右。如果写入的数据超过了这个限制,写操作将会阻塞直到有足够的空间可用。

        3、本地通信。无名管道只能在同一台机器上的进程间使用,不能跨越网络边界。

        4、有亲缘关系的进程。无名管道主要用于父子进程或者兄弟进程之间,因为只有这些进程可以共享由共同祖先创建的文件描述符。

        5、非持久化。无名管道是临时性的,当所有引用它的文件描述符都被关闭时,它就会被销毁。

无名管道的创建

        要创建一个无名管道,我们可以使用pipe函数。其函数原型如下。

int pipe(int pipefd[2]);

        各个参数和返回值的含义如下。

        pipefd:一个整型数组,用来存储两个文件描述符。数组的第一个元素是读端的文件描述符,第二个元素是写端的文件描述符。这两个文件描述符可以像普通文件一样,使用read和write函数来操作。

        返回值:成功时返回0,并且会将两个新的文件描述符填充到传入的pipefd数组中。失败时返回-1,并设置全局变量errno来表示具体的错误原因。

无名管道的使用

        一旦创建了无名管道,我们便可以利用它来进行进程间的通信。通常的做法是在父进程中创建管道,然后通过fork函数来创建子进程。接着,根据需要关闭不必要的文件描述符(比如:父进程中可能不需要读端,子进程中可能不需要写端),以确保数据流只朝一个方向进行流动。最后,父进程和子进程分别从各自的端点读取或写入数据。

        在下面的示例代码中,父进程创建了一个管道,然后调用fork来创建子进程。子进程继承了父进程的文件描述符,但随后关闭了不需要的写端。父进程则关闭了不需要的读端,并向管道中写入了一条消息。子进程从管道中读取消息,并打印到标准输出。

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

int main()
{
    int pipefd[2];
    if (pipe(pipefd) == -1)
    {
        printf("pipe failed\n");
        return -1;
    }

    pid_t cpid = fork();
    if (cpid == -1)
    {
        printf("fork failed\n");
        return -1;
    }

    if (cpid == 0)
    {
        // 子进程,关闭写端
        close(pipefd[1]);

        char buf = 0;
        while (read(pipefd[0], &buf, 1) > 0)
        {
            write(STDOUT_FILENO, &buf, 1);
        }

        write(STDOUT_FILENO, "\n", 1);
        close(pipefd[0]);
        _exit(EXIT_SUCCESS);
    }
    else
    {
        // 父进程,关闭读端
        close(pipefd[0]);
        const char *pszMsg = "Hello, Hope_Wisdom";
        write(pipefd[1], pszMsg, strlen(pszMsg));
        close(pipefd[1]);

        // 等待子进程结束
        wait(NULL);
    }

    return 0;
}


http://www.niftyadmin.cn/n/5862961.html

相关文章

长尾关键词增效逻辑:SEO搜索可见度与精准捕获

内容概要 随着搜索引擎算法智能化的深化&#xff0c;长尾关键词的战略价值已从辅助工具演变为SEO优化的核心支点。本文构建的增效逻辑框架揭示&#xff1a;在流量红利消退的竞争环境下&#xff0c;长尾词库的精准度与内容匹配效率直接决定搜索可见度的提升幅度&#xff0c;并最…

如何在 Ubuntu 上安装 Docker:详细步骤指南

文章目录 前言一、更新软件包列表二、安装 Docker三、启动并启用 Docker 服务四、验证 Docker 安装五、检查 Docker 服务状态六、将当前用户加入 Docker 组&#xff08;可选&#xff09;七、测试 Docker 是否正常运行八、安装 Podman-Docker&#xff08;可选&#xff09;九、总…

【CI/CD】CI/CD环境搭建流程和持续集成环境配置

文章目录 CI/CD环境搭建流程一、GitLab 安装与配置1. 环境准备2. 安装依赖3. 下载安装GitLab4. 修改配置5. 应用配置并启动6. 初始化设置 二、GitLab 项目管理1. 创建群组与项目2. 用户管理3. 上传代码 三、Jenkins 安装与配置1. 安装JDK172. 安装Jenkins3. 修改配置4. 启动服务…

Linux命令终极指南:从入门到精通掌握150+核心指令

一、文件与目录管理 1. 基础导航 pwd # 显示当前工作目录 (Print Working Directory) ls -lah # 列出所有文件包括隐藏文件&#xff0c;人性化大小显示# -l 长格式 -a 所有文件 -h 易读大小 cd ~ # 切换到用户家目录 (Change Directory) cd - # 返回上…

一周学会Flask3 Python Web开发-flask3模块化blueprint配置

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 我们在项目开发的时候&#xff0c;多多少少会划分几个或者几十个业务模块&#xff0c;如果把这些模块的视图方法都写在app.py…

C++ ——继承

体现的是代码复用的思想 1、子类继承父类&#xff0c;子类就拥有了父类的特性&#xff08;成员方法和成员属性&#xff09; 2、已存在的类被称为“基类”或者“父类”或者“超类”&#xff1b;新创建的类被称为“派生类”或者“子类” 注意&#xff1a; &#xff08;1&#…

数据结构之【顺序表简介】

1.顺序表的概念 顺序表 是 用一段物理地址连续的存储单元 依次 存储数据元素的线性结构 一般情况下采用数组存储 2.顺序表的结构 既然顺序表可以用来存储数据元素&#xff0c; 那就少不了 增删查改 的操作 此时&#xff0c;单一地只创建数组满足不了上述操作 创建相应的结构…

【git-hub项目:YOLOs-CPP】本地实现05:项目移植

ok&#xff0c;经过前3个博客&#xff0c;我们实现了项目的跑通。 但是&#xff0c;通常情况下&#xff0c;我们的项目都是需要在其他电脑上也跑通&#xff0c;才对。 然而&#xff0c;经过测试&#xff0c;目前出现了2 个bug。 项目一键下载【⬇️⬇️⬇️】&#xff1a; 精…