正确的代码 - 带 popen 的非阻塞管道
Correct Code - Non-blocking pipe with popen
关于
非阻塞管道有很多问题,但没有可以复制和粘贴(几乎不需要更正)和使用的代码示例。
我从这个线程中得到了想法和来源:使用popen的不堵塞管道?
但是如何使用它呢?在while
周期? 请查看我的更改。真的需要使用errno == EAGAIN
和额外的标头#include <cerrno>
吗?如果需要,建议您拥有更好的版本:
FILE *pipe;
char buff[512];
if ( !(pipe = popen( command.c_str(), "r")) ) return false;
int d = fileno(pipe);
while ( true )
{
ssize_t r = read(d, buff, sizeof(buff));
if (r == -1 && errno == EAGAIN) // really need errno?
continue;
else if (r > 0)
ptr_output->append(buff);
else
break;
}
pclose(pipe);
是的。如果read
调用返回错误值 ( -1
) 并且errno
设置为 EAGAIN
,则表示没有可用的数据,因此您continue
循环重试。如果你摆脱了errno
,错误将被有效地忽略,你的程序可能会崩溃。想象一下,如果你确实删除了它:当read
返回-1
,但是,比如说,错误是管道坏了(另一端关闭了它),你只会继续尝试循环并进入无限循环。坏主意。
在我的 Linux 多线程应用程序中 (Ubuntu 16.04, x86_64, Native POSIX Threads, libc.so.6 version Ubuntu GLIBC 2.23-0ubuntu9)此代码
int fd = fileno(pipe);
fcntl(fd, F_SETFL, O_NONBLOCK);
while (true)
{
ssize_t r = read(fd, buff, sizeof(buff));
if ((r == -1) && (errno == EAGAIN)) // really need errno?
continue;
else
{
if (r > 0)
result += buff;
else
break;
}
}
即使有fctnl(...)
原因也会失败,因为不仅命令输出,而且经常读取来自RAM的许多其他任意值。我认为这是由于代码的线程不安全。
(示例:按 20 个线程并行执行 echo
3 个值 10、30 和 40,read
值并仅显示最后一个值。输出: 40 QIh MIh 40 40 30...)
此答案中的另一个代码工作正常fgets
因为实现是线程安全的:
while (!feof(pipe))
{
if (fgets(buff, sizeof(buff), pipe) != NULL)
result += buff;
}
相关文章:
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- IPC使用多个管道和分支进程来运行Python程序
- 如何创建函数管道,以便函数一个接一个地运行?
- Gstreamer 管道从命令 lne 到 c 代码
- 自动"yes"到 Popen SSH 命令
- 外壳包装器句柄/执行交互式命令管道C++ UNIX
- 将旧管道转换为现代 openGL 时出现问题
- 如何使用管道在父级和子级之间来回传递文件
- 在没有管理员权限的情况下连接到同一网络中的命名管道
- 如何测量管道延迟?
- 我如何使用此程序管道多个命令?C++
- 先进先出:一个进程永远不会从管道读取
- Node.js fs.open() 在尝试打开 4 个以上的命名管道 (FIFO) 后挂起
- 使用模板而不是虚拟方法的管道模式
- bash脚本在使用popen()时不返回代码以调用C ++程序
- 我可以写入关闭的套接字并强制纠正损坏的管道错误吗?
- 在 Azure DevOps 构建管道中使用英特尔C++编译器为 Linux 环境构建C++代码
- popen 管道执行程序和读取输出的替代方法
- 正确的代码 - 带 popen 的非阻塞管道
- 将stdin重定向到管道(popen)C++