我正在实现一个命名管道来在 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) 过多,系统将开始失败。