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; };