FIFO管道中的数据丢失?
Posted
技术标签:
【中文标题】FIFO管道中的数据丢失?【英文标题】:Loss of data in a FIFO pipe? 【发布时间】:2015-05-06 22:39:56 【问题描述】:我有一个 python 进程写入一个命名管道,一个 C++ 程序读取它。 (我用 C++ 创建管道)。嗯,它似乎工作正常。但是,有时我注意到有数据丢失。读取器未检测到数据!我做错了吗?
这是我创建管道的方式:
void create_pipes(string pipename)
char * cstr1 = new char [pipename.length()+1];
strcpy (cstr1, pipename.c_str());
cout << "Creating " << pipename << " pipe..." << endl;
unlink (cstr1); // Delete pipe
int result = mkfifo (cstr1, S_IRUSR| S_IWUSR); // Create Pipe
if( result == -1 )
cout << "There was en error creating the pipe! " << result << endl;
//return 0;
else
cout << "Pipe created!" << endl;
现在,我有一个线程可以像这样读取管道:
int fd = open(cstr1, O_RDONLY); // Open the pipe
while( running_threads )
if(!read(fd, buf, MAX_BUF))
continue;
string line(buf);
if( buf != "" )
//cout << line;
pipe_r.DECODE_PIPE_DATA(line);
cout << "Thread terminated" << endl;
close(fd);
在 python 中,我只是通过这样做将数据写入管道:
def write_pipe(file_string):
while True:
try:
pipe.write(file_string)
pipe.flush()
break
except:
print "Error while writing to pipe"
continue
什么可能导致我的问题? python程序将数据写入管道成功;但是 c++ 程序有时不会读取管道。这可能是由于 python 进程在实际读取数据之前写入数据的速度比 C++ 程序快吗?我该怎么办?
谢谢。
【问题讨论】:
Tangent:为什么不直接将pipename.c_str()
传递给unlink
和mkfifo
?您编写的代码不必要地分配内存(然后忘记释放它)。
if(!read(fd, buf, MAX_BUF))
-- 你把read
的结果扔掉了,所以你不知道你读了多少数据。代码不可能工作。
【参考方案1】:
buf
不保证会被终止,也不保证不会在您发布的代码中嵌入'\0'
字符。这应该会更好,但如果 Python 代码在其写入的数据中嵌入 '\0'
,则仍可能会失败:
while( running_threads )
ssize_t bytesRead = read(fd, buf, MAX_BUF);
if ( bytesRead < 0 )
break;
else if ( bytesRead == 0 )
continue;
string line( buf, static_cast<size_t>(bytesRead) );
如果read()
返回 -1,您的代码没有正确处理错误情况。
【讨论】:
即使有嵌入的空值也应该可以工作。std::string
可以包含任意数据。
@Brian,真的。但他使用的构造函数假定 C 风格的字符串是输入数据。 (我承认buf
被定义为char *
或char []
。)
我的意思是,你的代码使用了正确的构造函数,所以它不会遇到同样的问题。还是我误会了什么?
我使用了指定输入字符串长度的构造函数。我不记得如果 '\0'
嵌入到带有该构造函数的这样的字符串中会发生什么。这就是为什么我说它“可能仍然失败”。但它确实可以防止溢出,而原始代码没有。根据cplusplus.com/reference/string/string/string,string( const char *, size_t )
构造函数复制指定的字节数。所以它应该工作。但我不记得曾经使用过那个构造函数。
所以要明确一点...我的 python 代码不应该发送 '\0' 字符?以上是关于FIFO管道中的数据丢失?的主要内容,如果未能解决你的问题,请参考以下文章
为啥这里举例说明在 LINUX 中使用命名管道 -FIFO 的程序会遇到竞争条件?