IPC:管道

news2024/12/23 10:41:05

一、管道的概念

1.原理

在进程3G~4G的内核空间中,创建一个特殊的文件(管道),管道的数据直接保存在内存中。

2.特性

1)管道可以看成是一个特殊的文件,一般的文件存储在外存中,而管道内容是存储在内存中。

2)管道遵循先进先出的原则。(队列形式实现)

3)对于管道的读操作是一次性的,被读取的数据会从管道中删除

4)管道是一种半双工的通信方式

a、单工:只能A发消息给B,B不能发消息给A

b、半双工:同一时间,只能A发消息给B,或者B发消息给A

c、全双工:同一时间,AB能够互相发消息

5)对于管道的操作,只能使用文件IO函数,因为需要直接操作内核空间。例如open,close,read,write。但是不能使用 lseek 函数。

6)当管道的读写端均关闭时,管道内存空间会被释放

7)管道的大小:65536bytes=64K

8)从管道中读取数据

  • 当管道的读写端均存在,
    1. 当管道中没有数据的时候,read函数阻塞。
    2. 当管道中拥有的数据为10个,读取5个,实际读取5个
    3. 当管道中拥有的数据为5个,读取10个,实际读取5个
  • 当管道的写端不存在的时候后,(父子进程中均有写端,均关闭)
    1. 当管道中有数据的时候,会先将管道中的所有数据读取完毕
    2. 当管道中没有数据的时候,read函数不会阻塞,立即返回0;

9)向管道中写入数据

  • 当管道的读写端均存在,
    1. 将管道写满后,write函数会阻塞。
  • 当管道的读端不存在的时候,(父子进程中均有读端,均关闭)
    1. 调用write函数,尝试向管道中写入数据会导致调用write函数的进程退出。
    2. 调用write函数的进程会收到管道破裂信号(SIGPIPE),管破裂信号的处理函数会让进程退出。

二、无名管道(pipe)

  1. 无名管道即没有名字的管道文件,即在文件系统中不可见的管道文件。
  2. 无名管道使用的时候无法使用open函数打开文件,因为不知道路径以及名字。
  3. 无名管道只能用于具有 亲缘关系 的进程间通信。

为什么无名管道只能用于具有 亲缘关系 的进程间通信。

  1. 无名管道在文件系统中不可见,所以两个无关的进程,无法拿到同一根管道的读写端。
  2. 子进程会继承父进程的文件描述符表,所以在父进程中创建一根管道拿到读写端后,调用fork函数,创建出来的子进程也会有该管道的读写端。

pipe:创建一个无名管道,同时打开无名管道的读写端

int pipe(int pipefd[2]);

参数:

int pipefd[2]:需要传入一个整型数组的首地址,且数组的容量为2。

                        用于存储两个打开的文件描述符;

                        pipefd[0]:读端

                        pipefd[1]: 写端

返回值: 成功,返回0; 失败,返回-1,更新errno;

三、有名管道

有名字的管道文件,但是管道的数据依然保存在内存中

有名管道的特点:

  1. 有名管道是有名字的管道,即在文件系统中可以看到路径以及名字的管道文件。
  2. 有名管道由于在文件系统中可见,所有无亲缘关系的进程,可以通过open函数打开同一根有名管道。
  3. 有名管道可以使用在 无亲缘关系 的进程间通信。

创建有名管道

1.shell指令:终端输入mkfifo

mkfifo ./fifo

2.用mkfifo函数创建:创建一个有名管道

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

参数:

char *pathname:指定要创建的有名管道路径以及名字;

mode_t mode:有名管道的权限,真实的权限的mode & ~umask:0664 0777

the permissions of the created file are (mode & ~umask).

返回值:

成功,返回0;

失败,返回-1,更新errno;

文件已经存在的错误是一个合法的错误,需要排除,代码允许正常运行

#define EEXIST 17

可用access()函数来判断用户是否具有访问某个文件的权限

需要包含#include<unistd.h>

 int access(const char *pathname,int mode)
 参数:
         pathname:表示要测试的文件的路径
         mode:表示测试的模式可能的值有:
         R_OK:是否具有读权限
         W_OK:是否具有可写权限
         X_OK:是否具有可执行权限
         F_OK:文件是否存在
返回值:若测试成功则返回0,否则返回-1

可用access函数来判断管道文件是否已经存在,

if(access("./myfifo",F_OK)==-1){
    //如果管道文件myfifo不存在的话,则创建管道文件
    mkfifo("myfifo",0666);
}    

有名管道的使用

  1. 通过open函数打开有名管道,close关闭有名管道
  2. 通过read write函数读写有名管道,与读写普通文件一致。

O_RDONLY: 只读

O_WRONLY: 只写

O_RDWR : 读写

----以上三种必须,且只能包含一种-----

O_NONBLOCK 非阻塞形式

  1. flags == O_WRONLY
    1. open函数会阻塞,当有另外一个进程 以读 的方式打开同一根FIFO时候,解除阻塞。
  2. flags == O_RDONLY
    1. open函数会阻塞,当有另外一个进程 以写 的方式打开同一根FIFO时候,解除阻塞。
  3. flags == O_RDWR
    1. open函数不会阻塞,函数运行成功,管道的读写端均被打开
  4. flags == O_WRONLY | O_NONBLOCK
    1. open函数不阻塞,open函数会运行失败,此时写端打开失败
  5. flags == O_RDONLY | O_NONBLOCK
    1. open函数不阻塞,open函数会运行成功,此时读端打开成功

默认情况下,当管道只有读端,或者只有写端的方式打开,open函数会阻塞。

直到读写端均被打开了,open函数解除阻塞。

四、代码

1.写端写入

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

int main(int argc, const char *argv[])
{
    umask(0);

    //创建有名管道
    if(mkfifo("./myfifo", 0664) < 0)                                      
    {   
        //文件已经存在的错误是一个合法的错误,需要排除,代码允许正常运行
        if(17 != errno)     //EEXIST != errno
        {
            perror("mkfifo");
            return -1; 
        }
    }   
    printf("myfifo create success\n");

    //以只写的方式打开有名管道, 阻塞
    int fd = open("./myfifo", O_WRONLY);
    if(fd < 0)
    {   
        perror("open");
        return -1; 
    }   
    printf("open fifo success wronly  fd=%d\n", fd);

    char buf[128] = ""; 
    while(1)
    {   
        printf("请输入>>>");
        fgets(buf, sizeof(buf), stdin);
        buf[strlen(buf)-1] = 0;

        if(write(fd, buf, sizeof(buf)) < 0)
        {
            perror("write");
            return -1; 
        }
        if(strcasecmp(buf, "quit") == 0)    //忽略大小写的比较
            break;

        printf("写入成功\n");
    }   

    close(fd);
    return 0;
}

2.读端读取

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

int main(int argc, const char *argv[])
{                                                                                            
    umask(0);

    //创建有名管道
    if(mkfifo("./myfifo", 0664) < 0)
    {
        //文件已经存在的错误是一个合法的错误,需要排除,代码允许正常运行
        if(17 != errno)     //EEXIST != errno
        {
            perror("mkfifo");
            return -1;
        }
    }
    printf("myfifo create success\n");

    //以只读的方式打开有名管道, 阻塞
    int fd = open("./myfifo", O_RDONLY);
    if(fd < 0)
    {
        perror("open");
        return -1;
    }
    printf("open fifo success rdonly  fd=%d\n", fd);

    char buf[128] = "";
    ssize_t res = 0;
    while(1)
    {
        bzero(buf, sizeof(buf));
        res = read(fd, buf, sizeof(buf));
        if(res < 0)
        {
            perror("read");
            return -1;
        }
        else if(0 == res)
        {
            printf("写端退出\n");
            break;
        }
        printf("res=%ld : buf=%s\n", res, buf);
        if(strcasecmp(buf, "quit") == 0)
            break;
    }

    close(fd);
    return 0;
}

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

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

相关文章

“光谱视界革新:ChatGPT在成像光谱遥感中的智能革命“

遥感技术主要通过卫星和飞机从远处观察和测量我们的环境&#xff0c;是理解和监测地球物理、化学和生物系统的基石。ChatGPT是由OpenAI开发的最先进的语言模型&#xff0c;在理解和生成人类语言方面表现出了非凡的能力。本文重点介绍ChatGPT在遥感中的应用&#xff0c;人工智能…

docker——启动各种服务

1.Mysql 2.Redis 3.nginx 4.ES 注意&#xff1a;ES7之后环境为 -e ELASTICSEARCH_HOSTS http://ip地址:9200

双场板功率型GaN HEMT中用于精确开关行为的电容建模

来源:Capacitance Modeling in Dual Field-Plate Power GaN HEMT for Accurate Switching Behavior (TED 16年) 摘要 本文提出了一种基于表面电势的紧凑模型&#xff0c;用于描述具有栅极和源极场板&#xff08;FP&#xff09;结构的AlGaN/GaN高电子迁移率晶体管&#xff08;…

在OpenStack架构中,Controller节点的配置(基础)

虚拟机的安装 新建虚拟机&#xff0c;选择自定义 默认选择即可 操作系统的镜像稍后选择 客户及操作系统选择Linux&#xff0c;注意选择centos 7 64位 给虚拟机命名 处理器的配置建议1&#xff1a;2 内存大小选择建议为&#xff1a;4GB 网络连接选择为&#xff1a;NAT 默认即可…

Redis底层核心对象RedisObject源码分析

文章目录 1. redis底层数据结构2. 插入KV底层源码流程分析 1. redis底层数据结构 redis 6数据结构和底层数据结构的关系 String类型本质是SDS动态字符串&#xff0c;即redis层面的数据结构底层会有对应的数据结构实现&#xff0c;上面是redis 6之前的实现 redis 7数据结构和底…

如何保证消息的顺序性

先看看顺序会错乱的场景&#xff1a;RabbitMQ&#xff1a;一个 queue&#xff0c;多个 consumer&#xff0c;这不明显乱了&#xff1a; 解决方案&#xff1a;

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的番茄新鲜程度检测系统(深度学习+UI界面+训练数据集)

摘要&#xff1a;本研究详述了一种采用深度学习技术的番茄新鲜程度检测系统&#xff0c;该系统集成了最新的YOLOv8算法&#xff0c;并与YOLOv7、YOLOv6、YOLOv5等早期算法进行了性能评估对比。该系统能够在各种媒介——包括图像、视频文件、实时视频流及批量文件中——准确地识…

智能泵站智能运维系统

在现代化城市建设和工农业发展中&#xff0c;泵站作为关键的水利设施&#xff0c;其运行效率和稳定性至关重要。然而&#xff0c;传统的泵站运维方式往往依赖于人工巡检和定期维护&#xff0c;这种方式不仅效率低下&#xff0c;而且难以应对突发状况。随着物联网技术的飞速发展…

支小蜜校园防欺凌系统真的能有效遏制欺凌现象吗?

随着社会的快速发展&#xff0c;校园欺凌问题逐渐浮出水面&#xff0c;引起了广泛关注。为了应对这一问题&#xff0c;校园防欺凌系统应运而生&#xff0c;旨在通过一系列措施&#xff0c;有效遏制欺凌现象的发生。然而&#xff0c;这一系统是否真的能够如预期般发挥作用&#…

软考高项(信息系统项目管理师)备考一、介绍

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

Cassandra 安装部署

文章目录 一、概述1.官方文档2. 克隆服务器3.安装准备3.1.安装 JDK 113.2.安装 Python3.3.下载文件 二、安装部署1.配置 Cassandra2.启动 Cassandra3.关闭Cassandra4.查看状态5.客户端连接服务器6.服务运行脚本 开源中间件 # Cassandrahttps://iothub.org.cn/docs/middleware/…

干货!不懂Python的math模块和random模块操作还不赶紧来学!

1.导入math模块 import math 2.向上取整&#xff1a;math.ceil() num 9.12print(math.ceil(num)) # 10 3.向下取整&#xff1a;math.floor() num1 9.99print(math.floor(num1)) # 9 4.开平方&#xff1a;math.sqrt()​​​​​​​ num2 16print(math.sqrt(num…

Python程序控制

一、程序的描述方式 1.1自然语言 &#xff08;1&#xff09;概念&#xff1a;自然语言就是使用人类语言、直接描述程序 &#xff08;2&#xff09;比如&#xff1a;之前提过的Input&#xff08;输入&#xff09;、Process&#xff08;处理&#xff09;、Output&#xff08;输…

RabbitMQ - 02 - 基本消息模型

目录 部署demo项目 什么是基本消息模型 实现基本消息模型 部署demo项目 首先配置好一个mq的练习demo,并配置好相关依赖 链接&#xff1a;https://pan.baidu.com/s/1oXAqgoz9Y_5V7YxC_rLa-Q?pwdv2sg 提取码&#xff1a;v2sg 如图 父xml文件已经配置好了 AMQP依赖了 什么…

1.Python是什么?——跟老吕学Python编程

1.Python是什么&#xff1f;——跟老吕学Python编程 Python是一种什么样的语言&#xff1f;Python的优点Python的缺点 Python发展历史Python的起源Python版本发展史 Python的价值学Python可以做什么职业&#xff1f;Python可以做什么应用&#xff1f; Python是一种什么样的语言…

【Java从入门到精通】Java异常处理

异常是程序中的一些错误&#xff0c;但并不是所有的错误都是异常&#xff0c;并且错误有时候是可以避免的。 比如说&#xff0c;你的代码少了一个分号&#xff0c;那么运行出来结果是提示是错误 java.lang.Error&#xff1b;如果你用System.out.println(11/0)&#xff0c;那么…

Linux 安装Nginx (Nginx-1.25.4)

一、下载Nginx安装包 1.服务器联网的情况下&#xff0c;使用wget命令把Nginx安装包下载到/usr/local/目录中&#xff0c;如果没有wget命令&#xff0c;需要先安装&#xff1a;yum install -y wget cd /usr/local wget -c https://nginx.org/download/nginx-1.25.4.tar.gz ng…

AndroidStudio设计登录页源码(音悦app)

目录 一、代码 二、效果 一、代码 1.在activity_main.xml里的代码 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent&quo…

elementUi中表格超出一行省略,鼠标放入显示完整提示

一、想要的效果 二、代码&#xff0c;加入show-overflow-tooltip即可 <el-table-column min-width"220" prop"content" show-overflow-tooltip> </el-table-column>

C语言深入理解指针(1)

前言 小陈也是学完了指针&#xff0c;还是有很多不多的地方&#xff0c;接下来会输出5篇博客去帮助自己彻底弄懂指针&#xff0c;以前的知识也需要复盘了呀。 内存和地址 1.1 内存 举个例子&#xff0c;去理解这两个的词&#xff0c;一个外卖员去送外卖&#xff0c;他首先需…