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

这篇具有很好参考价值的文章主要介绍了【Linux】进程间通信——命名管道。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

命名管道

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


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


1. 见一见管道文件

mkfifo函数

输入 man mkfifo 指令

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

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


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

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


输入 man 3 mkfifo 指令

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

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


管道文件的使用

【Linux】进程间通信——命名管道
将hello world 重定向到fifo管道中
但是好像并不会写入
fifo只代表一种符号,向符号写入消息并不会刷新到磁盘上,而是只会把hello world写到管道中
但是管道文件是内存文件,所以大小不会改变


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

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

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

2. 命名管道原理

【Linux】进程间通信——命名管道
要打开对应的文件,就会在操作系统内创建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连续生成可执行程序

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

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


为了不让client和server成为目标文件
【Linux】进程间通信——命名管道

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

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函数创建管道文件

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

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


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

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


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

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


手动删除fifo后,再次运行
【Linux】进程间通信——命名管道

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

2. 让读写端进程分别按照自己的需求打开文件
【Linux】进程间通信——命名管道

将文件描述符内容打印到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 客户端

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

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

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


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

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

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

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


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

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

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


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

当终端1运行client时,输入对应的信息,终端2中会自动显示出来
client端可以将信息发送给server端
文章来源地址https://www.toymoban.com/news/detail-414016.html

完整代码
//客户端
#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;
}

到了这里,关于【Linux】进程间通信——命名管道的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux】进程通信之匿名管道通信

    我们往往需要多个进程协同,共同完成一些事情。 数据传输:一个进程需要将它的数据发送给另一个进程 资源共享:多个进程之间共享同样的资源。 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止 时要通知父进程)。

    2024年04月14日
    浏览(35)
  • 【LInux】进程间通信 -- 匿名管道

    我们在学习进程管理,进程替换时,都强调了 进程的独立性 ,那进程间通信是什么?这好像和进程的独立性 相矛盾 吧? 那么今天,我们就来学习 进程间通信 ,和第一种通信方式 – 管道 进程间通信,并没有破坏进程的独立性这一特点,这点我们在 管道 讲解 而进程通信的

    2023年04月19日
    浏览(25)
  • Linux进程间通信【匿名管道】

    ✨个人主页: 北 海 🎉所属专栏: Linux学习之旅 🎃操作环境: CentOS 7.6 阿里云远程服务器 进程间通信简称为 IPC (Interprocess communication),是两个不同进程间进行任务协同的必要基础。进行通信时,首先需要确保不同进程之间构建联系,其次再根据不同的使用场景选择不同

    2024年02月08日
    浏览(37)
  • Linux--进程间的通信-匿名管道

    进程间通信(IPC,Interprocess Communication)是指在不同进程之间传输数据和交换信息的一种机制。它允许多个进程在同一操作系统中同时运行,并实现彼此之间的协作 。 进程间通信方式: 管道(Pipe) : 管道是最基本的进程间通信方式 ,它是一种 半双工 的通信方式,通过管

    2024年04月14日
    浏览(32)
  • [Linux]进程间通信(上篇)——匿名管道(管道原理,实现示例,端口情况探究!!)

            hello,大家好,本篇文章介绍Linux进程间的通信,包含内容有进程间通信的介绍、理解,管道的介绍使用:匿名管道,匿名管道的实现示例,匿名管道端口4种情况的探究。    目录  1️⃣进程间通信  🍙进程间通信目的 🍙进程间通信分类 🍙进程间通信的技术背景

    2024年02月14日
    浏览(39)
  • 【Linux】进程间通信——命名管道

    匿名管道只能用来进行进程间通信,让具有血缘关系的进程进行通信 让毫不相关的进程之间进行通信,就需要采用命名管道通信 因为该文件有文件名称的,而且必须要有,所以叫做命名管道 mkfifo函数 输入 man mkfifo 指令 制作一个 FIFOS ,表示命名管道 mkfifo fifo 制作一个管道

    2023年04月15日
    浏览(24)
  • 【Linux】进程间通信 -- 命名管道

    在管道的通信中,除了 匿名管道 ,还有一个 命名管道 。 匿名管道只支持具有 “亲戚关系” 的进程间通信,而命名管道就可以支持不同的,任意的进程通信。 那就下来就开始我们今天的学习。 匿名管道的两种使用方式: 指令的 \\\' | \\\' 和pipe()函数 命名管道也有两种使用方式

    2023年04月20日
    浏览(24)
  • linux——进程间通信——命名管道

     ✅1主页::我的代码爱吃辣 📃2知识讲解:Linux——进程间通信——命名管道 ☂️3开发环境:Centos7 💬4前言:命名管道是一种特殊的文件存放在文件系统中,而不是像管道那样存放在内核中。命名管道可以用于任何两个进程间的通信,而不限于同源的两个进程。当进程对

    2024年02月08日
    浏览(37)
  • Linux进程间通信【命名管道】

    ✨个人主页: 北 海 🎉所属专栏: Linux学习之旅 🎃操作环境: CentOS 7.6 阿里云远程服务器 命名管道通信属于 IPC 的其中一种方式,作为管道家族,命名管道的特点就是 自带同步与互斥机制、数据单向流通 ,与匿名管道不同的是:命名管道有自己的名字,因此可以被没有血

    2024年02月08日
    浏览(26)
  • 【看表情包学Linux】IPC 进程间通信 | PIPE 管道 | 匿名管道 | 管道通信的原理 | 系统调用: pipe 接口

       🤣  爆笑 教程  👉 《看表情包学Linux》 🔥 CSDN 累计订阅量破千的火爆 C/C++ 教程的 2023 重制版,C 语言入门到实践的精品级趣味教程。 了解更多: 👉  \\\"不太正经\\\" 的专栏介绍  ← 试读第一章 订阅链接: 🔗 《C语言趣味教程》 ← 猛戳订阅! 目录 Ⅰ. 进程间通信(I

    2024年02月14日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包