服务器编程之--用命名管道(FIFO)来做进程间通信
2015-01-20 15:40
465 查看
最近在研究进程间通信,要实现两个非亲缘关系的进程间进行通信,用匿名管道不行,只能用命名管道。
有名管道简介
也称FIFO,系统提供一个路径名与此管道关联,以FIFO形式存在与文件系统中。
生存周期从被创建开始,到该管道文件被删除(进程结束不会造成管道消失)。
数据在管道之间以无格式流式传递。
只需要建立一个有名管道便可进行读写操作。遵从FIFO原则,不保证操作的原子性。
优点是使用方便简单,可以作为任何进程间通信手段,缺点是功能上有很多限制。
命名管道FIFO网上一搜一大堆,在这里我主要分享一下,如果做到进程间流畅地通信,实用为主
1. 首先创建管道
创建成功之后 你会发现在/gyl 目录下有fiforead ,fifowrite 两个管道文件
![](http://img.blog.csdn.net/20150120151209890?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ3VveWlsb25nZWR1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
另外每次创建管道时,应将原来的管道删除掉
delpipe.sh
2. 之后了创建一个服务端server,一个客户端client
客户端先读,服务端写,之后客户再写,服务端读,就是这样一个交互过程
服务端代码 server.cpp
客户端代码 client.cpp
编译比较简单 g++ -o server server.cpp
g++ -o client client.cpp
首先运行./client
![](http://img.blog.csdn.net/20150120152331688?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ3VveWlsb25nZWR1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
再运行./server
![](http://img.blog.csdn.net/20150120152412687?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ3VveWlsb25nZWR1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
另外有一个问题,在最后说一下,通常创建管道时,不成功而且提示 operation not permited 也是权限不允许,这时候就检查一下目录权限
为什么/gyl/这个目录可以呢 ,可以看下一张图
![](http://img.blog.csdn.net/20150120152846843?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ3VveWlsb25nZWR1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
可以看到这个目录是 drwxrwxrwt 权限,其他目录下不成功,得加上这个权限
![](http://img.blog.csdn.net/20150120153128596?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ3VveWlsb25nZWR1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
具体方法如上
管道通信的功能还是没有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
有名管道简介
也称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; }
创建成功之后 你会发现在/gyl 目录下有fiforead ,fifowrite 两个管道文件
另外每次创建管道时,应将原来的管道删除掉
system("./delpipe.sh"); 这段代码就是这个作用
delpipe.sh
#!/bin/bash rm /gyl/fifowrite rm /gyl/fiforead
2. 之后了创建一个服务端server,一个客户端client
客户端先读,服务端写,之后客户再写,服务端读,就是这样一个交互过程
服务端代码 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); } } }
客户端代码 client.cpp
#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 server server.cpp
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
相关文章推荐
- Linux系统编程——进程间通信:命名管道(FIFO)
- !!!Windows系统编程之进程间通信---异步管道和命名管道
- Linux进程间通信(IPC)之二——命名管道(FIFO)
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
- linux 系统编程-学习笔记10--进程间通信--管道/FIFO/消息队列/
- Linux环境进程间通信(一)——管道(pipe)和命名管道(fifo)
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
- 【进程间通信】普通管道和命名管道(FIFO)
- 进程间通信___命名管道(FIFO)
- 不相关进程间通信--命名管道(FIFO文件)
- 不相关进程间通信--命名管道(FIFO文件)
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
- 【Linux】进程间通信-命名管道FIFO
- UNIX环境高级编程学习之第十五章进程间通信 - 通过有名管道(命名管道)实现进程间通信
- 进程间通信--FIFO命名管道
- Linux下进程间通信机制:FIFO(命名管道)
- 【Linux】进程间通信-命名管道FIFO
- Linux环境进程间通信(一)——管道(pipe)和命名管道(fifo)
- 进程间通信系列 之 命名管道FIFO及其应用实例
- Linux进程间通信之命名管道(FIFO)