关于非阻塞管道有很多问题,但是没有代码可以复制和粘贴(几乎没有更正)并使用过。
我从这个帖子中得到了这个想法和来源: Non-blocking pipe using popen?
但如何使用它?在while
周期?请检查我的更改。是否真的需要使用errno == EAGAIN
&amp;附加标题#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);
答案 0 :(得分:1)
是。如果read
调用返回错误值(-1
)且 errno
设置为EAGAIN
,则表示没有可用数据,所以你continue
循环再试一次。如果你摆脱errno
,错误将被有效忽略,你的程序可能会崩溃。想象一下,如果你删除了它:当read
返回-1
时,但是,错误是管道坏了(另一端关闭它),你会继续尝试循环并输入一个无限循环。馊主意。
答案 1 :(得分:0)
在我的Linux多线程应用程序(Ubuntu 16.04,x86_64,Native POSIX Threads,libc.so.6版本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中的许多其他任意值。我认为这是由于线程不安全的代码。
(示例:执行echo
3个值,10,30和40,并行20个线程,read
值并仅显示最后一个值。输出:40 QIh MIh 40 40 30 ...)
另一个代码from this answer正常,因为fgets
实施线程安全:
while (!feof(pipe))
{
if (fgets(buff, sizeof(buff), pipe) != NULL)
result += buff;
}