2

关于非阻塞管道有很多问题,但是没有可以复制和粘贴(几乎没有更正)和使用的代码示例。

我从这个线程中得到了想法和来源: Non-blocking pipe using 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);
4

2 回答 2

1

是的。如果read调用返回错误值 ( -1) errno设置为EAGAIN,则表示没有可用数据,因此您continue循环再试一次。如果你去掉errno,错误将被有效地忽略,你的程序可能会崩溃。想象一下,如果您确实删除了它:当read返回-1时,例如,错误是管道已损坏(另一端将其关闭),您将继续尝试循环并进入无限循环。馊主意。

于 2012-06-09T15:15:52.563 回答
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由 20 个线程并行执行 3 个值,10、30 和 40,read这些值仅显示最后一个值。输出:40 QIh MIh 40 40 30...)

由于fgets实现是线程安全的,因此该答案中的另一个代码可以正常工作

while (!feof(pipe))
{
    if (fgets(buff, sizeof(buff), pipe) != NULL)
    result += buff;
}
于 2017-08-26T18:41:07.007 回答