名为 Fifo 的管道

名为 Fifo 的管道

我正在实现一个命名管道来在 cpp 中的两个进程之间写入和读取数据。第一个进程从图像中实时获取特征点,而第二个进程读取该特征点。它工作正常,但在两个进程之间进行几次数据交换后,谈话者代码冻结了。我知道我需要关闭一个管道以便能够从中读取数据,当我尝试在 while 循环之外关闭 talker 代码中的文件描述符时,侦听器文件无法访问变量的新值。我目前找不到解决方法。我可能会错过什么?

下面是将变量写入 fifo 文件的函数的 MCVE:

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <opencv2/opencv.hpp>

/*Function Prototypes*/
void(cv::Mat frame);    
int(talker);

 int talker(float depthright)
 {
   int fd;
   char depthstring[1024];    
   sprintf(depthstring, "%4.4f", depthright);

   char * myfifo = "/tmp/myfifo";

   mkfifo(myfifo, 0666);           /* create the FIFO (named pipe) */
   fd = open(myfifo, O_WRONLY/* | O_NONBLOCK*/);       
   write(fd, depthstring, sizeof(depthright) );    

   /* close FIFO and delete fifo names from file system */
   close(fd);
   unlink(myfifo); 

   return 0;
}

int main( int argc, char* argv[] )
{
 cv::Mat frame;
//convert frame to grayscale, equalize histogram of grayed frame
//detect faces and then detect eyes; acquire eye depth values as depthright
 talker(depthright);     //call fifo talker funtion
return 0;
 }

监听者如下:

int main()
 {    
  int fd;
  char * myfifo = "/tmp/myfifo";
  char buf[1024];

    while(1)
    {
        //READ actual depth fifo
        fd = open(myfifo, O_RDONLY | O_NONBLOCK);
        read(fd, buf, MAX_BUF);
        float depth = strtof(buf, NULL);
        printf("\ndepth actual: %4.2f", depth);              
    }    

     //Close read buffers
     close(fd);

     return 0;
  }

答案1

您只发送sizeof(float)字节,它只是 的子字符串depthstring,其实际大小是strlen(depthstring)+1,而不是sizeof(float)

您可以做的一件事是消除与字符串的转换。由于读取命名 FIFO 的两个进程都在同一台机器上(不,FIFO 不能通过 NFS 工作),因此您可以假设 afloat在两个进程中以相同的方式表示。所以:

int talker(float depthright)
 {
   int fd;
   const char * myfifo = "/tmp/myfifo";

   mkfifo(myfifo, 0666);           /* create the FIFO (named pipe) */
   fd = open(myfifo, O_WRONLY/* | O_NONBLOCK*/);
   write(fd, &depthright, sizeof(depthright) );    

   /* close FIFO and delete fifo names from file system */
   close(fd);
   /* Don't delete the FIFO yet. The reader may not have opened
    * it yet.
    */

   return 0;
}

进而:

int main()
 {    
  int fd;
  const char * myfifo = "/tmp/myfifo";

    while(1)
    {
        //READ actual depth fifo
        fd = open(myfifo, O_RDONLY | O_NONBLOCK);
        float depth;
        read(fd, &depth, sizeof(depth));
        // Close read buffers now, since we open it with
        // each iteration. Waiting until after the loop
        // will result in only the last fd being closed.

        // Furthermore, there's a tight limit on how many
        // FDs you can have open at once.
        close(fd);    
        printf("\ndepth actual: %4.2f", depth);
        // Without this, libc may hold the output in a buffer
        // until the next float is read.
        fflush(stdout);
    }    
     /* NOT REACHED. The compiler may actually delete this code, since
      *  it can prove that this part will never be executed.
      */ 
     unlink(myfifo); 
     return 0;
  }

答案2

您的问题的一小部分可能在于您正在循环open内部执行操作while (1) … read(没有关闭循环中生成的文件描述符)。您的代码预计会为 FIFO 积累数百个文件描述符。通常,在达到一千个后,open由于打开的文件 (EMFILE) 过多,系统将开始失败。

相关内容