Linux系统编程系列之进程间通信(IPC)-管道

news2024/9/28 3:21:00

一、什么是管道

        在Linux系统下,一切皆文件,所以管道就是一个文件,用来实现进程间通信的一种方式。分析小技巧:对于一些陌生的概念,都把它当成是文件,然后操作的时候,就是三部曲。文件打开,文件读写,文件关闭。

二、有哪几种管道

        匿名管道具名管道。有些地方又称为无名管道和有名管道。

三、管道的特性

        1、匿名管道(PIPE)

               (1) 匿名管道没有名称,因此无法使用open创建或者打开,事实上匿名管道有自己独特的创建接口。

                (2)匿名管道只能用于父子进程之间的通信,不能用于别的进程。因为匿名管道没有名称,别的进程无法创建和打开,二而父子进程遵循读时共享,写时复制的原则,自然就能够拿到匿名管道的文件描述符,然后就可以通信。

                (3)匿名管道描述符只能通过继承的方式传递给后代进程,只能用于亲缘进程间(通常用于父子进程间)的通信。

                (4)匿名管道拥有两个文件描述符,一个专用于读fd[0],一个专用于写fd[1],因此在创建管道时,必须传递一个至少包含两个整型元素的数组。

                (5)不能有多个进程同时对匿名管道进行写操作,否则数据有可能被覆盖。

匿名管道适用于一对一的、具有亲缘关系的进程间的通信。

        2、具名管道(FIFO)

                (1)具名管道通常被称为FIFO(First In First Out),存放的数据都是按顺序被读出的

                (2)具名管道更接近普通文件,有文件名,可以使用open()函数打开,支持read()/write()等读写操作。

                (3)有专门的接口创建:mkfifo()。创建新的具名管道文件时,必须保证创建路径位于Linux系统内,尤其是虚拟机种操作的时候,不可将管道文件创建在共享文件夹中,因为共享文件夹是windows系统的,不支持管道文件。

                (4)支持多路同时写入。

         3、管道读写特性

           管道文件默认是阻塞的,可以修改文件描述的阻塞特性来达到目的。

四、管道的接口API有哪些

// 匿名管道
#include <unistd.h>

int pipe(int fd[2]);

返回值:成功返回0, 失败返回-1



// 具名管道
#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);

返回值:成功返回0, 失败返回-1

五、案例

        1、匿名管道

#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>


int main(int argc, char *argv[])
{
    int fd[2];

    int ret = pipe(fd); // 创建匿名管道
    if(ret == -1)
    {
        perror("pipe fail\n");
        return -1;
    }

    char msg[128] = {0};
    pid_t pid = fork(); // 创建子进程
    if(pid > 0)     // 父进程
    {
        while(1)
        {
            printf("please input data:");
            scanf("%s", msg);
            // 匿名管道fd[1]是写入端
            write(fd[1], msg, strlen(msg));
            bzero(msg, sizeof(msg));
        }
    }
    else if(pid == 0)   // 子进程
    {
        int i = 1;
        int ret = 0;
        
        while(1)
        {
            bzero(msg, sizeof(msg));
            while(1)
            {
                // 匿名管道fd[0]是接收端
                ret = read(fd[0], msg, 128);
                
                if(i == 1)
                {
                    printf("\nrecv data from parent process:\n");
                    i--;
                }
                
                printf("%s", msg);
                if(ret < 128)
                {
                    i = 1;
                    printf("\n");
                    break;
                } 
            }
        }
    }
    else
    {
        perror("fork fail\n");
        return -1;
    }


    return 0;
}

        2、具名管道

// 具名管道操作示例

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define FIFO_PATH "/tmp/fifo.txt"   // 具名管道文件路径,不能在共享文件夹路径下创建

int main(int argc, char *argv[])
{
    int ret = access(FIFO_PATH, F_OK);  // 判断管道文件是否存在
    if(ret == -1)
    {
        ret = mkfifo(FIFO_PATH, 0777);   // 不存在就创建具名管道
        if(ret == -1)
        {
            perror("mkfifo fail\n");
            return -1;
        }
    }

    int fd = open(FIFO_PATH, O_RDWR);   // 打开管道文件
    if(fd == -1)
    {
        perror("open fail\n");
        return -1;
    }
    
    char msg[128] = {0};
    pid_t pid = fork();
    if(pid > 0) // 父进程
    {
        while(1)
        {
            printf("please input data: ");
            scanf("%s", msg);
            write(fd, msg, strlen(msg));    // 像普通文件操作一样写入数据
            bzero(msg, sizeof(msg));
        }
    }
    else if(pid == 0)   // 子进程
    {
        int i = 1;
        int ret1 = 0;
        while(1)
        {
            while(1)
            {
                bzero(msg, 128);
                ret1 = read(fd, msg, 128);  // 像普通文件一样读取数据

                if(i == 1)
                {
                    printf("recv data from parent process:");
                    i = 0;
                }
                printf("%s", msg);
                if(ret1 < 128)
                {
                    i = 1;
                    printf("\n");
                    break;
                }
            }            
        }
    }
    else
    {
        perror("fork fail\n");
        close(fd);  // 关闭管道文件
        return -1;
    }

    close(fd);  // 关闭管道文件

    return 0;
}

        3、设置非阻塞特性

// 管道非阻塞操作示例

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define FIFO_PATH   "/tmp/fifo.txt"


int main(int argc, char *argv[])
{
    int ret = access(FIFO_PATH, F_OK);
    if(ret == -1)
    {
        ret = mkfifo(FIFO_PATH, 0777);
        if(ret == -1)
        {
            perror("mkfifo fail\n");
            return -1;
        }
    }

    int fd = open(FIFO_PATH, O_RDWR);
    if(fd == -1)
    {
        perror("open fail\n");
        return -1;
    }

    // 设置非阻塞特性
    int status = fcntl(fd, F_GETFL); // 获取文件特性
    status |= O_NONBLOCK;   // 加上非阻塞特性
    fcntl(fd, F_SETFL, status);     // 重新设置文件特性


    char msg[128] = {0};

    while(1)
    {

        printf("read data:\n");
        ret = read(fd, msg, 128);   // 非阻塞状态下会一直循环
        if(ret <= 0 )
        {
            printf("no data\n");
        }
        else
        {
            printf("%s\n", msg);
        }
        sleep(1); // 加上睡眠可以减少程序对CPU的占用
    }

    close(fd);

    return 0;
}

六、总结

        匿名管道用于通常用于父子进程间的通信,而具名管道用于任何多个进程间的通信,管道文件默认是阻塞的,管道的数据读取都是按顺序的,不能使用lseek()函数跳过某个字节。

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

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

相关文章

香港服务器是什么?

香港服务器是指位于香港地区的云服务器或物理服务器。香港作为一个重要的国际金融和商业中心&#xff0c;具有良好的地理位置和先进的网络基础设施。香港服务器提供稳定的网络连接和高性能&#xff0c;可用于托管网站、应用程序和数据存储等各种互联网服务。 香港服务器具有以…

精准测试——持续测试

前面已经介绍了黑盒测试和白盒测试。从前面的介绍中可以知道&#xff0c;黑盒测试是一种面向业务流程的测试&#xff0c;针对需求设计测试用例&#xff0c;在运行的系统上执行测试用例&#xff0c;完成测试。 整个测试过程中测试工程师对于测试代码是如何运行的一无所知&#…

深度学习算法模型转成算能科技平台xx.bmodel模型的方法步骤

目录 1 docker镜像下载 2 SDK下载 3 下载sophon-demo 4 修改docker镜像的脚本 5 创建个文件夹 6.source 7.转模型 1 docker镜像下载 可以在dockerhub看到镜像的相关信息 https://hub.docker.com/r/sophgo/tpuc_dev/tags 用下面的命令下载 docker pull sophgo/tpuc_d…

vim练习题

在普通模式 / 可以用来寻找 . 是重复上次的动作&#xff0c;$ 是移动到末尾 直接查找 .vimrc 保存后重启 安装curl 出现问题 宏 通过记录在寄存器中&#xff0c;让寄存器知道怎么操作 宏只能在1 2 4 寄存器上面使用 替代命令&#xff0c;将匹配到的&#xff0c;包括这些内容…

【力扣每日一题】2023.8.27 合并区间

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 那么合并区间是在什么情况下才能合并呢&#xff1f; 我总结为两种情况 第一种情况就是这样&#xff0c;第二个区间的左区间大于第一个区…

算法通关村第十四关——堆

堆是将一组数据按照完全二叉树的存储顺序&#xff0c;将数据存储在一个一维数组中的结构。堆有两种结构&#xff0c;一种称为大顶堆&#xff0c;一种称为小顶堆&#xff0c;如下图。 小顶堆&#xff1a;任意节点的值均小于等于它的左右孩子&#xff0c;并且最小的值位于堆顶&am…

哪个蓝牙耳机打电话比较好,打电话降噪蓝牙耳机推荐

近年来&#xff0c;骨传导耳机的市场表现出了显著的增长&#xff0c;其市场竞争也变得异常激烈&#xff0c;与传统无线耳机相比&#xff0c;“骨传导耳机”的知名度还达不到举世皆知的地步&#xff0c;但对于运动群体以及部分有听力损伤的群体来说&#xff0c;骨传导耳机还是有…

大数据和人工智能之间如何的相互促进

文章目录 大数据为人工智能提供支持人工智能加速大数据的分析和应用紧密联系和合作方式综合效应&#xff1a;智能化决策和创新结论 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&…

回归预测 | MATLAB实现SSA-ELM麻雀搜索算法优化极限学习机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现SSA-ELM麻雀搜索算法优化极限学习机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现SSA-ELM麻雀搜索算法优化极限学习机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基…

Java基础数据结构

二叉查找树 二叉查找树&#xff0c;又称二叉树或者二叉搜索树 特点&#xff1a;每一个节点上最多又两个子节点 任意节点左子树上的值都小于当前节点 任意节点右子树上的值都大于当前节点 二叉查找树添加节点&#xff1a;规则 小的存左边 大的存右边 一样的不存 平衡二叉树&am…

小研究 - JVM 逃逸技术与 JRE 漏洞挖掘研究(二)

Java语言是最为流行的面向对象编程语言之一&#xff0c; Java运行时环境&#xff08;JRE&#xff09;拥有着非常大的用户群&#xff0c;其安全问题十分重要。近年来&#xff0c;由JRE漏洞引发的JVM逃逸攻击事件不断增多&#xff0c;对个人计算机安全造成了极大的威胁。研究JRE安…

libdrm全解析二十三 —— 源码全解析(20)

接前一篇文章&#xff1a;libdrm全解析二十二 —— 源码全解析&#xff08;19&#xff09; 本文参考以下博文&#xff1a; DRM 驱动程序开发&#xff08;VKMS&#xff09; 特此致谢&#xff01; 前一篇文章已提到&#xff0c;drmModeGetResources函数值得深入地进行讲解。本回…

C语言练习题Day1

从今天开始分享C语言的练习题&#xff0c;每天都分享&#xff0c;差不多持续16天&#xff0c;看完对C语言的理解可能更进一步&#xff0c;让我们开始今天的分享吧&#xff01; 题目一 执行下面的代码&#xff0c;输出结果是&#xff08;&#xff09; int x5,y7; void swap()…

Vue2向Vue3过度核心技术自定义指令

目录 1 自定义指令1.指令介绍2.自定义指令3.自定义指令语法4.指令中的配置项介绍5.代码示例6.总结 2 自定义指令-指令的值1.需求2.语法3.代码示例 3 自定义指令-v-loading指令的封装1.场景2.需求3.分析4.实现5.准备代码 1 自定义指令 1.指令介绍 内置指令&#xff1a;v-html、v…

基于JSP+Servlet+mysql学生宿舍管理系统

基于JSPServletmysql学生宿舍管理系统 一、系统介绍二、功能展示四、其它1.其他系统实现五.获取源码 一、系统介绍 项目类型&#xff1a;Java web项目 项目名称&#xff1a;基于JSPServlet的学生宿舍管理系统[sushe] 项目架构&#xff1a;B/S架构 开发语言&#xff1a;Java…

免费开源跨平台视频下载器 支持数百站点视频和音频下载-ytDownloader

ytDownloader&#xff1a; ytDownloader是一款免费开源跨平台视频下载器&#xff0c;帮助用户从数百个网站下载不同格式的视频和提取音频&#xff0c;使用简单&#xff0c;复制视频链接粘贴即可下载&#xff0c;支持4K画质视频下载&#xff0c;支持Linux、Windows 和 macOS平台…

DBO优化SVM的电力负荷预测,附MATLAB代码

今天为大家带来一期基于DBO-SVM的电力负荷预测。 原理详解 文章对支持向量机(SVM)的两个参数进行优化&#xff0c;分别是&#xff1a;惩罚系数c和 gamma。 其中&#xff0c;惩罚系数c表示对误差的宽容度。c越高&#xff0c;说明越不能容忍出现误差,容易过拟合。c越小&#xff0…

基于Java+SpringBoot+Vue前后端分离图书电子商务网站设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

大数据(二)大数据行业相关统计数据

大数据&#xff08;二&#xff09;大数据行业相关统计数据 目录 一、大数据相关的各种资讯 二、转载自网络的大数据统计数据 2.1、国家大数据政策 2.2、产业结构分析 2.3、应用结构分析 2.4、数据中心 2.5、云计算 一、大数据相关的各种资讯 1. 据IDC预测&#xff0…

软件工程(十五) 行为型设计模式(一)

1、责任链模式 简要说明 通过多个对象处理的请求,减少请求的发送者与接收者之间的耦合。将接受对象链接起来,在链中传递请求,直到有一个对象处理这个请求。 速记关键字 传递职责 类图如下 由类图可以比较容易的看出来,其实就是自己关联自己,形成了一个链,并且自己有…