【linux】命名管道

简介: 【linux】命名管道

1.命名管道原理

2.代码实现命名管道

首先认识一个函数,他可以形成一个命名管道

头文件:

#include <sys/types.h>
 #include <sys/stat.h>

函数体:

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

第一个参数是新建的命名管道放在哪个路径下的路径字符串,第二个参数为该文件的打开权限


同时shell提供指令 mkfifo +命名管道名也能形成管道,会新建在当前路径下


unlink函数实现删除管道

头文件:

#include <unistd.h>

函数体:

int unlink(const char *pathname);

参数为命名管道文件的所在路径


总规划

1.send.cc该进程进行发送数据

2.reception.cc该进程进行接收数据

3.namepipe.hpp该文件进行配置环境

4.makefile对两个.cc文件进行编译

1.makefile编写

.PHONY:all
all:send reception
send:send.cc
     g++ -o send send.cc -std=c++11
reception:reception.cc
     g++ -o reception reception.cc -std=c++11
.PHONY:clean
clean:
     rm -rf send reception

2.namepipe.hpp先完成命名管道的创建以及删除操作

我们使用cpp,可以用类来封装管道的创建以及删除

namepipe.hpp

#include<iostream>
#include <sys/types.h>  //mkfifo的头文件open头文件
#include<string>
#include <sys/stat.h>   //mkfifo的头文件open头文件
#include <unistd.h>     //unlink头文件/close头文件
using namespace std;
const string com_path="./myfifo";
#define Defaultfd -1
#define Creater 1
#define User 2
class Namepipe
{
public: 
Namepipe(const string &path,int who)
:_fifo_path(path)
,_id(who)
,_fd(Defaultfd)
{
 
 if(_id==Creater)
 {
  int ret=mkfifo(_fifo_path.c_str(),0666);
     if(ret!=0)
       {
        perror("mkfifo");
       }
       cout<<"creater create named pipe"<<endl;
 }
}
~Namepipe()
{
if(_id==Creater)
{
 int ret=unlink(_fifo_path.c_str());
 if(ret!=0)
    {
    perror("unlink");
    }
    cout<<"creater free namepipe"<<endl;
}
if(_fd!= Defaultfd)close(_fd);
}
private:
     const string _fifo_path;
     int _id;
     int _fd;
};

send.cc

#include"namepipe.hpp"
int main()
{
Namepipe fifo(com_path,User);
}

reception.cc

#include"namepipe.hpp"
int main()
{Namepipe fifo(com_path,Creater);
}

3. send .cc文件,reception.cc打开命名管道文件,分配文件操作符

reception.cc

#include"namepipe.hpp"
int main()
{Namepipe fifo(com_path,Creater);
 if(fifo.openforread())
   {
   cout<<"reception open name pipe done"<<endl;
  
   }
}

send .cc

#include"namepipe.hpp"
int main()
{
Namepipe fifo(com_path,User);
if(fifo.openforwrite())
 {
  cout<<"send open namepipe done"<<endl;
 }
}

namepipe.hpp

为了更清楚的展示,没有写构造和析构

#define Read O_RDONLY
#define Write O_WRONLY
#define Basesize 1024
class Namepipe
{
   private:
   bool opennamepipe(int mode)
   {
   _fd=open(_fifo_path.c_str(),mode);
   if(_fd<0)
    return false;
    return true;
   }
public: 
bool openforread()
{return opennamepipe(Read);
}
bool openforwrite()
{
return opennamepipe(Write);
}
private:
     const string _fifo_path;
     int _id;
     int _fd;
};

该步骤完成后,如上图所示


4.send进程写入命名管道数据

send.cc

#include"namepipe.hpp"
int main()
{
Namepipe fifo(com_path,User);
if(fifo.openforwrite())
 {
  cout<<"send open namepipe done"<<endl;
  while(true)
     {
     cout<<"please Enter>";
     string message;
     getline(cin,message);
     fifo.writenamepipe(message);
         
     }
 }
 return 0;
}

namepipe.hpp(只保留本步骤的)

#define Basesize 1024
class Namepipe
{
 
public: 
int writenamepipe(const string &in)
{
 return write(_fd,in.c_str(),in.size());
}
private:
     const string _fifo_path;
     int _id;
     int _fd;
};


5.reception进程读内核缓冲区的数据

namepipe.hpp

class Namepipe
{
public: 
int readnamepipe(string *out)
{
char buffer[Basesize];
int n=read(_fd,buffer,sizeof(buffer));
if(n>0)
{buffer[n]=0;
*out=buffer;
}
return n;
}
private:
     const string _fifo_path;
     int _id;
     int _fd;
};

reception.cc

#include"namepipe.hpp"
int main()
{Namepipe fifo(com_path,Creater);
 if(fifo.openforread())
   {
   cout<<"reception open name pipe done"<<endl;
   
   while(true)
   {
   string message;
   int n=fifo.readnamepipe(&message);
   if(n>0)
   {
   cout<<"send say>"<<message<<endl;
   }
   else if(n==0)
   {
   cout<<"send quit,reception too!"<<endl;
   break;
   }
   else 
   {
   cout<<"fifo.readnamepipe error"<<endl;
   break;
   }
   }
   
   }
}


整体代码

reception.cc

#include"namepipe.hpp"
int main()
{Namepipe fifo(com_path,Creater);
 if(fifo.openforread())
   {
   cout<<"reception open name pipe done"<<endl;
   
   while(true)
   {
   string message;
   int n=fifo.readnamepipe(&message);
   if(n>0)
   {
   cout<<"send say>"<<message<<endl;
   }
   else if(n==0)
   {
   cout<<"send quit,reception too!"<<endl;
   break;
   }
   else 
   {
   cout<<"fifo.readnamepipe error"<<endl;
   break;
   }
   }
   
   }
}

send.cc

#include"namepipe.hpp"
int main()
{
Namepipe fifo(com_path,User);
if(fifo.openforwrite())
 {
  cout<<"send open namepipe done"<<endl;
  while(true)
     {
     cout<<"please Enter>";
     string message;
     getline(cin,message);
     fifo.writenamepipe(message);
         
     }
 }
 return 0;
}

namepipe.hpp

#include<iostream>
#include <sys/types.h>  //mkfifo的头文件open头文件
#include<string>
#include <sys/stat.h>   //mkfifo的头文件open头文件
#include <unistd.h>     //unlink头文件/close头文件
#include <fcntl.h>      //open头文件
using namespace std;
const string com_path="./myfifo";
#define Defaultfd -1
#define Creater 1
#define User 2
#define Read O_RDONLY
#define Write O_WRONLY
#define Basesize 1024
class Namepipe
{
   private:
   bool opennamepipe(int mode)
   {
   _fd=open(_fifo_path.c_str(),mode);
   if(_fd<0)
    return false;
    return true;
   }
public: 
Namepipe(const string &path,int who)
:_fifo_path(path)
,_id(who)
,_fd(Defaultfd)
{
 
 if(_id==Creater)
 {
  int ret=mkfifo(_fifo_path.c_str(),0666);
     if(ret!=0)
       {
        perror("mkfifo");
       }
       cout<<"creater create named pipe"<<endl;
 }
}
~Namepipe()
{
if(_id==Creater)
{
 int ret=unlink(_fifo_path.c_str());
 if(ret!=0)
    {
    perror("unlink");
    }
    cout<<"creater free namepipe"<<endl;
}
if(_fd!= Defaultfd)close(_fd);
}
bool openforread()
{
return opennamepipe(Read);
}
bool openforwrite()
{
return opennamepipe(Write);
}
int writenamepipe(const string &in)
{
 return write(_fd,in.c_str(),in.size());
}
int readnamepipe(string *out)
{
char buffer[Basesize];
int n=read(_fd,buffer,sizeof(buffer));
if(n>0)
{buffer[n]=0;
*out=buffer;
}
return n;
}
private:
     const string _fifo_path;
     int _id;
     int _fd;
};


目录
相关文章
|
3月前
|
消息中间件 Linux 开发者
Linux进程间通信秘籍:管道、消息队列、信号量,一文让你彻底解锁!
【8月更文挑战第25天】本文概述了Linux系统中常用的五种进程间通信(IPC)模式:管道、消息队列、信号量、共享内存与套接字。通过示例代码展示了每种模式的应用场景。了解这些IPC机制及其特点有助于开发者根据具体需求选择合适的通信方式,促进多进程间的高效协作。
137 3
|
3月前
|
存储 Unix Linux
Linux I/O 重定向与管道
【8月更文挑战第17天】重定向在Linux中改变命令I/O流向,默认有&quot;&gt;&quot;覆盖输出至文件及&quot;&gt;&gt;&quot;追加输出至文件末尾,便于保存结果;使用&quot;&lt;&quot;从文件读取输入而非键盘,高效处理数据。文件描述符如0(stdin)、1(stdout)、2(stderr)标识I/O资源,支持读写操作。管道以&quot;|&quot;连接命令,使前一命令输出成为后一命令输入,如排序用户或找出CPU占用最高的进程,构建复杂数据处理流程。
46 9
|
3月前
|
存储 Linux 数据处理
在Linux中,什么是管道操作,以及如何使用它?
在Linux中,什么是管道操作,以及如何使用它?
|
3月前
|
存储 Unix Linux
Linux I/O 重定向与管道
【8月更文挑战第14天】输出重定向可将命令结果存入文件,如`&gt;`覆盖写入或`&gt;&gt;`追加写入。输入重定向从文件读取数据,如`&lt;`代替键盘输入。这些操作利用文件描述符(如0:stdin, 1:stdout, 2:stderr)管理I/O。管道`|`连接命令,使前一命令输出作为后一命令输入,便于数据处理,如排序用户`sort -t: -k3 -n /etc/passwd | head -3`或查找CPU占用高的进程`ps aux --sort=-%cpu | head -6`。
37 4
|
3月前
|
开发者 API Windows
从怀旧到革新:看WinForms如何在保持向后兼容性的前提下,借助.NET新平台的力量实现自我进化与应用现代化,让经典桌面应用焕发第二春——我们的WinForms应用转型之路深度剖析
【8月更文挑战第31天】在Windows桌面应用开发中,Windows Forms(WinForms)依然是许多开发者的首选。尽管.NET Framework已演进至.NET 5 及更高版本,WinForms 仍作为核心组件保留,支持现有代码库的同时引入新特性。开发者可将项目迁移至.NET Core,享受性能提升和跨平台能力。迁移时需注意API变更,确保应用平稳过渡。通过自定义样式或第三方控件库,还可增强视觉效果。结合.NET新功能,WinForms 应用不仅能延续既有投资,还能焕发新生。 示例代码展示了如何在.NET Core中创建包含按钮和标签的基本窗口,实现简单的用户交互。
66 0
|
3月前
|
消息中间件 Linux
Linux0.11 管道(十一)
Linux0.11 管道(十一)
25 0
|
3月前
|
数据挖掘 Linux 应用服务中间件
在Linux中,如何在Linux中使用管道?
在Linux中,如何在Linux中使用管道?
|
3月前
|
存储 Linux 数据处理
在Linux中,管道(pipe)和重定向(redirection)的是什么?
在Linux中,管道(pipe)和重定向(redirection)的是什么?
|
3月前
|
存储 Unix Linux
在Linux中,什么是管道?它是如何工作的?
在Linux中,什么是管道?它是如何工作的?
|
4月前
|
Linux
linux中 grep过滤查找 及 管道 ”|” 的使用
linux中 grep过滤查找 及 管道 ”|” 的使用