Chinaunix首页 | 论坛 | 博客
  • 博客访问: 347006
  • 博文数量: 88
  • 博客积分: 1695
  • 博客等级: 上尉
  • 技术积分: 1380
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-06 15:48
个人简介

喜欢美食, 旅行..

文章分类

全部博文(88)

文章存档

2014年(2)

2013年(12)

2012年(14)

2010年(8)

2009年(52)

我的朋友

分类: LINUX

2012-12-08 17:34:33

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没有什么问题,程序工作得很好。
=======================================================================

废话还是不多说, 附上样例代码吧. 我已经简单测试过, 运行得挺好.

  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <fcntl.h>
  4. #include <unistd.h>

  5. #include <string>
  6. #include <cstring>
  7. #include<iostream>
  8. #include<algorithm>

  9. int readPipe(const char * namedPipe)
  10. {
  11.     int fd = open(namedPipe, O_RDWR, 0);
  12.     //int fd = open(namedPipe, O_RDONLY, 0);
  13.     if ( fd < 0 ) {
  14.         std::cout << "Open pipe failed!\n" << std::flush;
  15.         return -1;
  16.     }

  17.     static const size_t BUFF_LENGTH = 1024;
  18.     char r_buf[BUFF_LENGTH] = {0};
  19.     while (true) {
  20.         sleep(5); // Slepp for 5 secounds.
  21.         std::cout << "5 seconds had passed, let's check the pipe buffer: "
  22.                   << std::endl;
  23.         
  24.         memset(r_buf,0,BUFF_LENGTH);
  25.         size_t ret_size = read(fd, r_buf, BUFF_LENGTH);
  26.         if ( ret_size <= 0 )
  27.         {
  28.             std::cout << __FILE__<< "(" << __LINE__ << ")"
  29.                       << "unknow error happened on read function." << std::endl;
  30.             close(fd);
  31.             return -1;
  32.         }
  33.         
  34.         char * begin = static_cast<char*>(r_buf);
  35.         char * end = begin+BUFF_LENGTH;
  36.         do {
  37.             std::string strOut(begin);
  38.             std::cout << strOut << std::endl;
  39.             if ( strOut == "q" ||strOut == "quit" ||strOut == "exit" )
  40.             {
  41.                 close(fd);
  42.                 return 0;
  43.             }
  44.             
  45.             begin= std::find(begin,end,'\0');
  46.         } while( *(++begin) != '\0' );
  47.     }

  48.     close(fd);
  49.     return 0;
  50. }

  51. int writePipe(const char * namedPipe)
  52. {
  53.     int fd = open(namedPipe, O_RDWR, 0);
  54.     //int fd = open(namedPipe, O_WRONLY, 0);
  55.     if ( fd < 0 ) {
  56.         std::cout << "Open pipe failed!\n" << std::flush;
  57.         return -1;
  58.     }
  59.     while (true) {
  60.         std::string strIn;
  61.         std::cin >> strIn;
  62.         std::cout << "write " << strIn.size() << " bytes" << std::endl;

  63.         size_t sizeWrite = write(fd,strIn.c_str(),strIn.size()+1);
  64.         if ( sizeWrite <= 0 )
  65.         {
  66.             std::cout << __FILE__<< "(" << __LINE__ << ")"
  67.                       << "unknow error happen on write function." << std::endl;
  68.             close(fd);
  69.             return -1;
  70.         }

  71.         if ( strIn == "q" ||strIn == "quit" ||strIn == "exit" )
  72.         {
  73.             close(fd);
  74.             return 0;
  75.         }
  76.     }

  77.     close(fd);
  78.     return 0;
  79. }

  80. int main(int arc, char**arv)
  81. {
  82.     if (arc <=1) return -1;
  83.         
  84.     static const char * namedPipe = "/tmp/MyNamedPipe";
  85.     if ( mkfifo(namedPipe, S_IRUSR | S_IWUSR)< 0 && errno != EEXIST )
  86.     {
  87.         unlink(namedPipe);
  88.         std::cout << "Create named pipe failed! \n" << std::flush;
  89.         return -1;
  90.     }

  91.     std::string command = arv[1];
  92.     if (command == "write") writePipe(namedPipe);
  93.     if (command == "read") readPipe(namedPipe);

  94.     unlink(namedPipe);
  95.     return 0;
  96. }
再介绍一个更加实用的方案,假设一个叫functionBinary的可执行文件在标准输出里面打印了很多信息.
我们希望通过管道捕获这些打印信息到我们的程序里面来.
我们只要对上面的程序稍作修改就能办到 < 只需要修改函数 writePipe, 其他代码不变 >

  1. int writePipe(const char * namedPipe)
  2. {
  3.     std::string strCommand = "./functionBinary > ";
  4.     strCommand += namedPipe;
  5.     system(strCommand.c_str());
  6.     return 0;
  7. }

阅读(1504) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~