【Linux】进程间通信——命名管道

news2024/12/23 12:31:15

文章目录

  • 命名管道
    • 1. 见一见管道文件
      • mkfifo函数
      • 管道文件的使用
    • 2. 命名管道原理
      • 如何保证两个毫不相关的进程,看到的是同一个文件,并打开?
    • 3. 用命名管道实现server&client通信
      • 如何使用makefile连续生成可执行程序
      • comm.hpp文件
      • server.cc 服务端
        • 1. 创建一个管道文件
        • 2. 让读写端进程分别按照自己的需求打开文件
        • 3. 整体代码
      • client.cc 客户端
        • 完整代码

命名管道

匿名管道只能用来进行进程间通信,让具有血缘关系的进程进行通信
让毫不相关的进程之间进行通信,就需要采用命名管道通信


因为该文件有文件名称的,而且必须要有,所以叫做命名管道


1. 见一见管道文件

mkfifo函数

输入 man mkfifo 指令

制作一个 FIFOS ,表示命名管道


mkfifo fifo 制作一个管道 ,并命名为 fifo
文件类型以p开头,被称为管道文件


输入 man 3 mkfifo 指令

pathname代表路径,若不带路径只有文件名,默认在当前路径下
mode代表创建权限的模式 ,即创建文件的权限(666、664)
成功返回0,失败返回-1


管道文件的使用

在这里插入图片描述
将hello world 重定向到fifo管道中
但是好像并不会写入
fifo只代表一种符号,向符号写入消息并不会刷新到磁盘上,而是只会把hello world写到管道中
但是管道文件是内存文件,所以大小不会改变


通过赋值SSH渠道,创建终端2
在保证终端1的输出重定向 运行的情况下
cat默认从显示器中读取
在终端2中 使用输入重定向 将 fifo重定向到显示器中

最终在终端2中显示 hello world
而实际上 输出重定向和输入重定向 的启动都是进程,并且毫不相关

2. 命名管道原理

在这里插入图片描述
要打开对应的文件,就会在操作系统内创建struct file对象,struct file对象有自己的缓冲区
由于0 1 2 分别被占用,所以3指向struct file对象

若有一个毫不相关的进程,也打开磁盘中的文件,操作系统内部就不会再创建struct file对象,
会直接把struct file对象的地址填入新建立进程对应的下标里
在struct file对象中存在一个引用计数默认为1 ,当新创建一个进程时,引用计数就会变成2
此时两个进程指向同一份文件

目的是让两个进程之间进行通信,所以就不应该把数据刷到磁盘上,
应该把磁盘文件改为内存级的,不会进行刷盘,把它命名为管道文件

如何保证两个毫不相关的进程,看到的是同一个文件,并打开?

文件的唯一性,使用路径表示的
让不同的进程通过文件路径+文件名看到同一个文件,并打开,就是看到了同一个资源

3. 用命名管道实现server&client通信

在vscode中,分别创建server.cc文件和client.cc文件以及makefile

如何使用makefile连续生成可执行程序

若这样创建makefile,只会执行server可执行程序
server是从上到下扫描遇到的第一个真正的目标文件
makefile从上到下扫描时,会默认执行第一组依赖关系和依赖方法


为了不让client和server成为目标文件

这样就可以一次生成两个可执行程序了

comm.hpp文件

建立一个公共头文件 comm.hpp,在内部创建公共的路径以及mode
(以hpp结尾.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件)

#pragma once
#include<iostream>
#include<string>
#define NUM 1024
using namespace std;

const string fifoname="./fifo";//管道名字为当前路径创建的fifo
mode_t mode=0666;//默认权限为0666

这样 server文件和client文件就会调用同一份文件路径了

server.cc 服务端

1. 创建一个管道文件

创建server.cc文件,使用mkfifo函数创建管道文件


此时运行可执行程序,即可生成fifo管道文件


权限变为664 ,可是在comm.hpp中设置的权限为666
mode最终是要与umask进行操作的


手动将掩码置为0后,即可解决权限被修改的问题


手动删除fifo后,再次运行

此时权限还是666,没有被修改

2. 让读写端进程分别按照自己的需求打开文件

将文件描述符内容打印到buffer中
分为三种情况
若返回>0,则读取成功,而系统并不知道buffer是一个字符串,而我们自己知道,所以要在结尾加上\0
若返回==0,说明读到文件结尾,当写端关闭时,读端才会读到文件结尾
若返回<0,说明读取失败,则返回错误码

3. 整体代码

//服务端
#include<iostream>
using namespace std;
#include<sys/stat.h>
#include<sys/types.h>
#include<cerrno>
#include<cstring>
#include<fcntl.h>
#include<unistd.h>
#include"comm.hpp"//公共路径
int main()
{
    umask(0);//将当前进程的umask掩码设为0
  //创建管道文件,只需要创建一次
  int n=mkfifo(fifoname.c_str(),mode);
  if(n!=0)//创建失败
  {
    //失败就返回错误码
   cout<<errno<<":"<<strerror(errno)<<endl;
   return 1;
  }
   cout<<"create fifo success"<<endl;
   
   //2.让服务端直接开启管道文件
   int rfd=open(fifoname.c_str(),O_RDONLY);
   //第二个参数代表读
   //以读方式打开文件
   if(rfd<0)//创建失败
   {
     //失败就返回错误码
     cout<<errno<<":"<<strerror(errno)<<endl;
     return 2;
   }
   cout<<"open fifo success,begin"<<endl;

   // 3.正常通信
   char buffer[NUM];
   while(true)
   {
      buffer[0]=0;
    //rfd作为文件描述符(0/1/2)
      ssize_t n=read(rfd,buffer,sizeof(buffer)-1);//将rfd的内容读到buffer中
      if(n>0)//读取成功
      {
       buffer[n]='\0';
       cout<<"client#"<<buffer<<endl;
      }
      else if(n==0)//读到文件结尾为0
      {
          //写端关闭
          cout<<    "cilent quit,me too"<<endl;
          break;
      }
      else //读取失败
      {
         cout<<errno<<":"<<strerror(errno)<<endl;
         break;
      }
   }
   //关闭不要的fd
  close(rfd);
  unlink(fifoname.c_str());//删除文件fifo


    return 0;
}

client.cc 客户端

由于在服务端创建了管道文件,所以在客户端不用创建管道文件

直接打开文件即可,以写方式打开文件


为了避免输入的单词有空格存在
输入 man fgets 指令

从指定的流中获取字符串,并规定字符串的大小


因为有两个可执行程序存在,所以需要两个终端

当终端2没有运行server时,没有管道文件存在,而终端1运行server后,终端1中出现管道文件


当终端1运行client时,输入对应的信息,终端2中会自动显示出来
client端可以将信息发送给server端

完整代码

//客户端
#include<iostream>
using namespace std;
#include<sys/stat.h>
#include<sys/types.h>
#include<cerrno>
#include<cstring>
#include<fcntl.h>
#include<unistd.h>
#include<cstdio>
#include<cassert>
#include"comm.hpp"//公共路径
using namespace std;
int main()
{
   //不需要创建管道文件,打开文件即可
   int wfd=open(fifoname.c_str(),O_WRONLY);//以写的方式打开文件
   if(wfd<0)//说明打开失败
   {
     cout<<errno<<":"<<strerror(errno)<<endl;
     return 0;
   }

   //进行常规通信
   char buffer[NUM];
    while(true)
    {
        cout<<"请输入你的消息# ";
        char *msg=fgets(buffer,sizeof(buffer)-1,stdin);//将标准输入流的数据写入buffer中
        assert(msg);//检查是否为空
        (void)msg;//保证rlease模式发布依旧被使用
        //fgets会读取回车 即\n
        buffer[strlen(buffer)-1]=0;//12345\n  把\n位置覆盖为\0

        ssize_t n=write(wfd,buffer,strlen(buffer));
        assert(n>=0);
    }

   close(wfd);//关闭文件描述符
    return 0;
}

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

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

相关文章

如何通过 Baklib 平台实现知识共享(内含案例介绍)

在这个信息时代&#xff0c;知识被认为是最重要的资源之一。企业要想保持发展&#xff0c;就必须善于利用和管理知识。而知识管理则是一种涵盖人、过程和技术的活动&#xff0c;它通过收集、整理、传递和应用知识&#xff0c;使组织获得更高的效率、创造力和竞争力。本文将以知…

【Linux】八、Linux进程信号详解(一)

目录 一、认识信号 1.1 生活中的信号 1.2 将1.1的概念迁移到进程 1.3 信号概念 1.4 查看系统定义信号列表 1.5 man 7 signal 1.6 解释1.2的代码样例 1.7 信号处理常见方式概览 二、产生信号 2.1 signal函数 2.2 通过终端按键产生信号 2.3 调用系统函数向进程发信号…

前后端的身份认证【Node.js】

1. 前后端的身份认证 1.1 Web 开发模式 目前主流的 Web 开发模式有两种&#xff0c;分别是&#xff1a; &#xff08;1&#xff09;基于服务端渲染的传统 Web 开发模式 &#xff08;2&#xff09;基于前后端分离的新型 Web 开发模式 服务端渲染的传统 Web 开发模式 服务端渲染…

力扣面试题 08.06. 汉诺塔问题:思路分析+图文详解+代码实现

文章目录 第一部分&#xff1a;问题描述1.1 题目1.2 示例&#x1f340; 示例一&#x1f340; 示例二 1.3 提示 第二部分&#xff1a;思路分析第三部分&#xff1a;代码实现 第一部分&#xff1a;问题描述 1.1 题目 &#x1f3e0; 链接&#xff1a;面试题 08.06. 汉诺塔问题 -…

windows安装rabbitmq和环境erlang(最详细版,包括对应关系)

写在最前&#xff1a;不知何时起安装一个mq需要翻无数文章才能安上了&#xff0c;没有一个讲全的&#xff0c;这里写一个详细的教程。 删除旧版本对应关系: 1.在官方文档中找到RabbitMQ版本对应的Erlang版本重新下载安装包文档RabbitMQ Erlang Version Requirements — Rabbit…

大家副业都在做什么?csgo搬砖靠谱的副业推荐给你

从来没想过&#xff0c;以前只会玩CSGO的男孩子&#xff0c;现在居然能借助游戏赚到钱了&#xff01;甚至不需要什么专业的技巧&#xff0c;简简单单 在steam平台选择有利润的道具后&#xff0c;再上架到国内网易BUFF平台&#xff0c;赚取“信息差”差价而已&#xff01; 谁大…

itop-3568开发板驱动学习笔记(19)内核工作队列

《【北京迅为】itop-3568开发板驱动开发指南.pdf》 学习笔记 文章目录 工作队列简介共享工作队列工作结构体初始化 work_struct调度工作队列函数共享工作队列实验 自定义工作队列创建工作队列函数调度和取消调度工作队列刷新工作队列函数删除工作队列函数 内核延时工作队列延时…

成功上岸字节35K,技术4面+HR面,耗时20天,真是不容易

这次字节的面试&#xff0c;给我的感触很深&#xff0c;意识到基础的重要性。一共经历了五轮面试&#xff1a;技术4面&#xff0b;HR面。 下面看正文 本人自动专业毕业&#xff0c;压抑了五个多月&#xff0c;终于鼓起勇气&#xff0c;去字节面试&#xff0c;下面是我的面试过…

kali利用airgeddon破解WiFi (详细安装和使用教程)

目录 前言 一&#xff0c;软件&硬件环境 二&#xff0c;前期配置 Airgeddon安装和调试 #自带 #安装方法一 #安装方法二 #注意 网卡的配置 #打开服务 #加载网卡 三&#xff0c;运行操作 #检查 #主菜单 #打开监听模式 #查看周围可以攻击的网络 #截取…

vue - - - - - vue3全局配置挂载axios

vue3配置axios 1. 安装axios2. 配置拦截器3. vue.config.js代理配置4. 将axios全局挂载4. 文件内使用 1. 安装axios yarn add axios 2. 配置拦截器 创建文件 /src/utils/request.js "use strict";import Vue from "vue"; import axios from "axios&…

从现在起,请你不要用ChatGPT再做这4件事了

ChatGPT已经火爆了快半年了吧&#xff0c;紧接着国内也开始推出了各种仿制品&#xff0c;我甚至一度怀疑&#xff0c;如果人家没有推出ChatGPT&#xff0c;这些仿制品会不会出现。而很多人也嗨皮得不行&#xff0c;搭着梯子爬过高墙&#xff0c;用ChatGPT做各种觉得新鲜的事。但…

电脑可以开机但是无法进入到桌面怎么办?

电脑可以开机但是无法进入到桌面怎么办&#xff1f;有用户的电脑可以正确启动&#xff0c;但是电脑启动之后&#xff0c;却无法进入到系统桌面&#xff0c;而且卡在加载系统的页面中&#xff0c;或者是出现错误代码蓝屏了。这些情况其实都可以通过U盘来重装一个系统&#xff0c…

第七回:如何使用GirdView Widget

文章目录 概念介绍使用方法示例代码经验总结 我们在上一章回中介绍了Image Widget,本章回中将介绍 GirdView这种Widget&#xff0c;闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 在Flutter中使用GirdView表示网格状的布局&#xff0c;类似日常办公中使用的Excel…

hashCode 如何计算?这一篇就够了!

介绍 hashCode 中文‘散列码’&#xff0c;存在的意义是加快查找速率&#xff0c;可以在常数时间内进行寻址操作。 存在意义 它被定义在 Object 中&#xff0c;而 Object 类是一切类的父类&#xff0c;所以所有的方法都具有这个方法。 Java 中 hashCode 计算方式如下&#x…

C2. Exam in BerSU (hard version)(思维 + 小数据范围)

Problem - C2 - Codeforces 简单版本和困难版本之间的唯一区别是约束。 如果你用Python写一个解决方案&#xff0c;那么最好用PyPy发送&#xff0c;以加快执行时间。 贝兰德州立大学的一场会议已经开始。许多学生正在参加考试。 波利格拉夫维奇要对N个学生进行考试。学生们将…

工业树莓派远程I/O控制套装—更高效、更灵活、更便捷

一、背景 在完整的生产过程中&#xff0c;许多传感器设备和执行设备不完全安装在同一位置&#xff0c;大多分散部署在各个生产环节中。如果采用本地控制的方式&#xff0c;就需要用到多个控制器&#xff0c;但是成本较高&#xff0c;且不利于管理&#xff0c;所以最理想的解决…

2.redis-持久化

01-Redis持久化 概述 Redis数据存储在缓存中&#xff0c;为了防止数据的意外丢失&#xff0c;确保数据安全性。所以&#xff0c;就有了redis持久化。 分类 RDB: Redis默认的持久化策略, 直接存储数据 AOF: 存储数据的操作过程. 02-RDB持久化之save指令 配置说明 # 设置rdb…

[pgrx开发postgresql数据库扩展]2.安装与开发环境的搭建

——前文再续&#xff0c;书接上一回。 前言 我上篇文章刚刚写完&#xff0c;pgx就全面改名为了 pgrx……&#xff0c;结果导致我都来不及把以前的文章改过来&#xff0c;所以以后遵循最新的命名方法。 pgrx的开发环境需求 pgrx目前仅支持在linux操作系统上进行开发&#xff…

Android 基于 Perfetto 抓取 trace

Perfetto 官方链接地址 https://github.com/google/perfetto/ 开启Android的trace跟踪服务 Perfetto 是基于 Android 的系统追踪服务&#xff0c; 这个配置在 Android11 之后是默认打开的&#xff0c;但是如果你是 Android 9 ( P ) 或者 10 ( Q ) &#xff0c;那么就需要手动设…

【备考2023年软考】选系统规划与管理师,还是信息系统项目管理师?

目录 一、系统规划与管理师介绍 二、信息系统项目管理师介绍 三、二者区别 四、适合什么人考 五、怎么备考 1.了解考试大纲 2.系统学习&#xff08;附带资料分享&#xff09; 3.多做题 4.总结复习 软考系统规划与管理师和信息系统项目管理师是软考中的两个比较热门的证…