linux下的管道机制是需要两个进程有亲缘关系才可以的.但是命名管道(FIFO)却没有这个限制.
不过命名管道却有着下面的规则:
< 网上有个哥们儿总结得不错, 就先借用
他的原话了. >
a. 不使用O_NONBLOCK标志时,只读open要阻塞到某个其它进程为写而打开它为止
b. 不使用O_NONBLOCK标志时,只写open要阻塞到某个其它进程为读而打开它为止
c. 如果在open的时候指定O_NONBLOCK标志,当只读open时,没有进程为写而打开FIFO的话,会返回-1,只写open时,没有进程为读而打开FIFO的话也会返回-1表示失败。
以上的情况使FIFO的使用带来了一些不便,但有一个常用的技巧是,只要用O_RDWR(读写)来打开一个管道,则不会返回失败,而open也不会阻塞。两个进程使用FIFO来进行通信时,通常会使用两个FIFO,一个用于发送数据(即进行写操作),一个用于接收数据(即进行读操作),而这两个FIFO需要均使用O_RDWR来打开。使用系统调用open, read, write来操作这两个FIFO没有什么问题,程序工作得很好。
=======================================================================
废话还是不多说, 附上样例代码吧. 我已经简单测试过, 运行得挺好.
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <string>
- #include <cstring>
- #include<iostream>
- #include<algorithm>
- int readPipe(const char * namedPipe)
- {
- int fd = open(namedPipe, O_RDWR, 0);
- //int fd = open(namedPipe, O_RDONLY, 0);
- if ( fd < 0 ) {
- std::cout << "Open pipe failed!\n" << std::flush;
- return -1;
- }
- static const size_t BUFF_LENGTH = 1024;
- char r_buf[BUFF_LENGTH] = {0};
- while (true) {
- sleep(5); // Slepp for 5 secounds.
- std::cout << "5 seconds had passed, let's check the pipe buffer: "
- << std::endl;
-
- memset(r_buf,0,BUFF_LENGTH);
- size_t ret_size = read(fd, r_buf, BUFF_LENGTH);
- if ( ret_size <= 0 )
- {
- std::cout << __FILE__<< "(" << __LINE__ << "): "
- << "unknow error happened on read function." << std::endl;
- close(fd);
- return -1;
- }
-
- char * begin = static_cast<char*>(r_buf);
- char * end = begin+BUFF_LENGTH;
- do {
- std::string strOut(begin);
- std::cout << strOut << std::endl;
- if ( strOut == "q" ||strOut == "quit" ||strOut == "exit" )
- {
- close(fd);
- return 0;
- }
-
- begin= std::find(begin,end,'\0');
- } while( *(++begin) != '\0' );
- }
- close(fd);
- return 0;
- }
- int writePipe(const char * namedPipe)
- {
- int fd = open(namedPipe, O_RDWR, 0);
- //int fd = open(namedPipe, O_WRONLY, 0);
- if ( fd < 0 ) {
- std::cout << "Open pipe failed!\n" << std::flush;
- return -1;
- }
- while (true) {
- std::string strIn;
- std::cin >> strIn;
- std::cout << "write " << strIn.size() << " bytes" << std::endl;
- size_t sizeWrite = write(fd,strIn.c_str(),strIn.size()+1);
- if ( sizeWrite <= 0 )
- {
- std::cout << __FILE__<< "(" << __LINE__ << "): "
- << "unknow error happen on write function." << std::endl;
- close(fd);
- return -1;
- }
- if ( strIn == "q" ||strIn == "quit" ||strIn == "exit" )
- {
- close(fd);
- return 0;
- }
- }
- close(fd);
- return 0;
- }
- int main(int arc, char**arv)
- {
- if (arc <=1) return -1;
-
- static const char * namedPipe = "/tmp/MyNamedPipe";
- if ( mkfifo(namedPipe, S_IRUSR | S_IWUSR)< 0 && errno != EEXIST )
- {
- unlink(namedPipe);
- std::cout << "Create named pipe failed! \n" << std::flush;
- return -1;
- }
- std::string command = arv[1];
- if (command == "write") writePipe(namedPipe);
- if (command == "read") readPipe(namedPipe);
- unlink(namedPipe);
- return 0;
- }
再介绍一个更加实用的方案,假设一个叫
functionBinary的可执行文件在标准输出里面打印了很多信息.
我们希望通过管道捕获这些打印信息到我们的程序里面来.
我们只要对上面的程序稍作修改就能办到 < 只需要修改函数 writePipe, 其他代码不变 >
- int writePipe(const char * namedPipe)
- {
- std::string strCommand = "./functionBinary > ";
- strCommand += namedPipe;
- system(strCommand.c_str());
- return 0;
- }
阅读(1504) | 评论(0) | 转发(1) |