非阻塞读取FIFO时偶现数据丢失问题排查
问题分析与解决方案
你的reader程序偶尔无法读取到echo写入FIFO的内容,主要有以下几个原因:
1. FIFO文件名不匹配
你的程序打开的是当前目录下的the_fifo,但执行写入时用的是echo "[string]" > fifo_in——如果fifo_in和the_fifo不是同一个管道(比如名字拼写错误、不在同一目录),自然读不到数据。如果是偶尔写错文件名,就会出现“偶尔收不到”的现象。
2. 未处理read的错误返回值与空数据情况
你的代码忽略了read返回-1或0的情况,加上无间隔的死循环,会导致两个问题:
- 当
O_NONBLOCK模式下无数据可读时,read返回-1且errno=EAGAIN,此时代码会输出空字符串,同时持续占用100%CPU,可能影响系统调度,导致无法及时响应新的写入数据。 - 当写进程关闭FIFO后,
read返回0(EOF),代码同样输出空字符串,但后续新写进程的数据仍能被读取,不过CPU占用问题会加剧调度延迟。
3. 错误的输出逻辑
每次循环强制输出line并清空,即使没有读到任何数据,这会产生无效的空输出,同时如果因为调度延迟导致数据未被及时读取,也会出现“没收到”的错觉。
修复后的代码方案
方案一:使用阻塞模式(推荐,更可靠)
阻塞模式下,read会自动等待数据,无需循环轮询,CPU占用极低:
#include <iostream> #include <string> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> int main(int argc, char* argv[]) { int fd = open("the_fifo", O_RDONLY); if (fd == -1) { perror("open failed"); return 1; } char buf[32]; std::string line = ""; while(1) { ssize_t n_read = read(fd, buf, sizeof(buf)); if(n_read > 0) { line.append(buf, n_read); std::cout << line; std::cout.flush(); line = ""; } else if (n_read == 0) { // 写端关闭,下一次read会自动阻塞等待新的写进程 continue; } else { perror("read failed"); close(fd); return 1; } } close(fd); return 0; }
方案二:保留非阻塞模式但修复逻辑
如果必须使用非阻塞模式,需要添加错误处理和休眠逻辑,避免CPU占用过高:
#include <iostream> #include <string> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> int main(int argc, char* argv[]) { int fd = open("the_fifo", O_RDONLY | O_NONBLOCK); if (fd == -1) { perror("open failed"); return 1; } char buf[32]; std::string line = ""; while(1) { ssize_t n_read = read(fd, buf, sizeof(buf)); if(n_read > 0) { line.append(buf, n_read); std::cout << line; std::cout.flush(); line = ""; } else if (n_read == 0) { // 写端关闭,无需操作 continue; } else { if (errno != EAGAIN) { perror("read failed"); close(fd); return 1; } // 无数据时休眠,降低CPU占用 usleep(1000); } } close(fd); return 0; }
额外注意事项
- 确保写入命令的FIFO名称与程序打开的一致:执行
echo "[string]" > the_fifo(而非fifo_in)。 - 运行程序前,务必在当前目录执行
mkfifo the_fifo创建管道,且确保程序有读取权限。
内容的提问来源于stack exchange,提问作者Christian Chapman
相关产品推荐
相关产品推荐

