最近在研究进程间通信,要实现两个非亲缘关系的进程间进行通信,用匿名管道不行,只能用命名管道。
有名管道简介
也称FIFO,系统提供一个路径名与此管道关联,以FIFO形式存在与文件系统中。
生存周期从被创建开始,到该管道文件被删除(进程结束不会造成管道消失)。
数据在管道之间以无格式流式传递。
只需要建立一个有名管道便可进行读写操作。遵从FIFO原则,不保证操作的原子性。
优点是使用方便简单,可以作为任何进程间通信手段,缺点是功能上有很多限制。
命名管道FIFO网上一搜一大堆,在这里我主要分享一下,如果做到进程间流畅地通信,实用为主
1. 首先创建管道
#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<string.h> #include<stdlib.h> #include <iostream> #define FIFO_READ "/gyl/fiforead" #define FIFO_WRITE "/gyl/fifowrite" using namespace std; #define MASIZE 1024 int main() { int rfd,wfd; char buf[1024]; // 删除之前存在的管道 system("./delpipe.sh"); cout <<"create pipe fifo write ============>" <<endl; umask(0); // 创建写管道 if(mkfifo(FIFO_WRITE,S_IFIFO|0666) < 0) { perror("mkfifo"); exit(1); } cout <<"create pipe fifo write success --------->" <<endl; // 创建读管道 cout <<"create pipe fifo read ===============>" <<endl; if (mkfifo(FIFO_READ, S_IFIFO|0666) < 0) { perror("mkfifo"); exit(1); } cout <<"create pipe fifo read success ------------->" <<endl; umask(0); return 0; }
另外每次创建管道时,应将原来的管道删除掉
system("./delpipe.sh"); 这段代码就是这个作用
delpipe.sh
#!/bin/bash rm /gyl/fifowrite rm /gyl/fiforead
客户端先读,服务端写,之后客户再写,服务端读,就是这样一个交互过程
服务端代码 server.cpp
#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<string.h> #include<stdlib.h> #include <iostream> #include "memop.h" #define FIFO_READ "/gyl/fiforead" #define FIFO_WRITE "/gyl/fifowrite" using namespace std; #define MASIZE 1024 int main() { int rfd,wfd; char buf[1024]; cout <<"open write pipe : fifowrite =============>" <<endl; wfd=open(FIFO_WRITE,O_WRONLY); if(wfd==-1) { cout <<"open error for write " <<endl; perror("open"); exit(0); } cout <<"wfd = " <<wfd <<endl; cout <<"open read pipe : fiforead ===============>" <<endl; while((rfd=open(FIFO_READ,O_RDONLY))==-1) { cout <<"start to open ==============>" <<endl; sleep(1); } cout <<"rfd = " <<rfd <<endl; while(1) { memset(buf, 0, sizeof(buf)); printf("server: "); CMemOp kMemOp; kMemOp.InitWrite(); kMemOp.WriteInt(1008); kMemOp.WriteInt(234); kMemOp.GetBuffer(buf, sizeof(buf)); //scanf("%s",buf); int wNum = write(wfd,buf,kMemOp.GetBufferSize()); cout << "wNum = " <<wNum <<endl; memset(buf, 0, sizeof(buf)); printf("client:"); if(read(rfd,buf,1024)<0) { perror("read"); exit(1); } printf("%s\n",buf); if(strcmp(buf,"exit")==0) { exit(0); } } }
#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<stdlib.h> #include<sys/stat.h> #include<fcntl.h> #include<string.h> #include <iostream> #include "memop.h" using namespace std; #define FIFO_READ "/gyl/fifowrite" #define FIFO_WRITE "/gyl/fiforead" #define MASIZE 1024 int main() { int rfd,wfd; char buf[1024]; umask(0); cout <<"open read pipe: fifowrite =========>" <<endl; while((rfd=open(FIFO_READ,O_RDONLY))==-1){ sleep(1); } cout <<"rfd = " <<rfd <<endl; cout <<"open write pipe: fiforead ===========>" <<endl; wfd=open(FIFO_WRITE,O_WRONLY); if(wfd==-1){ perror("open"); exit(1); } cout <<"wfd = " <<wfd <<endl; while(1) { printf("server: "); memset(buf, 0, sizeof(buf)); int rLen = 0; if((rLen = read(rfd,buf,1024))<0) { perror("read"); exit(1); } CMemOp kMemOp; kMemOp.InitRead(buf, rLen); cout <<kMemOp.ReadInt() <<endl; cout <<kMemOp.ReadInt() <<endl; //cout <<buf <<endl; /* if(strcmp(buf,"exit")==0) { exit(0); } */ memset(buf, 0, sizeof(buf)); printf("client:"); scanf("%s",buf); write(wfd,buf,strlen(buf)); } }
g++ -o client client.cpp
首先运行./client
再运行./server
另外有一个问题,在最后说一下,通常创建管道时,不成功而且提示 operation not permited 也是权限不允许,这时候就检查一下目录权限
为什么/gyl/这个目录可以呢 ,可以看下一张图
可以看到这个目录是 drwxrwxrwt 权限,其他目录下不成功,得加上这个权限
具体方法如上
管道通信的功能还是没有socket通信那么功能强大而且灵活,既然是管道,数据只能从一头流向另向另一头,要想从另一头将数据流回当前这头,又得多一条管道。
在读写有名管道之前需要用open函数打开该有名管道,打开有名管道操作与其他文件有一定的区别,如果希望打开管道的写端,则需要另一个进程打开该管道的读端,如果只打开有名管道的一端,则系统将暂时阻塞打开进程,知道另一个进程打开管道的另一端,当前进程才会继s续执行,因此,在使用有名管道时一定么使用两个进程分别打开其读端和写端!
这是为什么要先启client ,因为最开始的读端在client上,如果不先启动client ,server 的写端一直阻塞在那里,先启动client 就能保证正常运行。
参考的一些文章
http://blog.csdn.net/jmy5945hh/article/details/7528395
http://www.cnblogs.com/TsengYuen/archive/2012/05/16/2504102.html
http://blog.chinaunix.net/uid-26983585-id-3345105.html