【问题标题】:Correct Code - Non-blocking pipe with popen正确的代码 - 带有 popen 的非阻塞管道
【发布时间】:2012-06-09 15:05:07
【问题描述】:

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

我从这个帖子中得到了想法和来源: 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);

【问题讨论】:

  • 管道不是非阻塞的,你没有复制'n'粘贴正确的代码。
  • @JonathanWakely !!!你太棒了!只有你发现它的阻塞!我没有 24 小时睡觉,并试图解决问题并失去一针,并且认为它没有帮助。也许现在我的线程不会慢下来。谢谢。
  • 你不应该这样编辑问题来支持a follow on questions。这让这个问题看起来很荒谬。改为重现新问题中的代码。

标签: c++ pipe popen


【解决方案1】:

是的。如果read 调用返回错误值(-1并且 errno 设置为EAGAIN,这意味着没有可用的数据,所以你continue 循环到再试一次。如果您摆脱了errno,错误将被有效地忽略,您的程序可能会崩溃。想象一下,如果您确实删除了它:当read 返回-1,但是,比如说,错误是管道坏了(另一端关闭了它),您将继续尝试循环并进入无限循环。馊主意。

【讨论】:

    【解决方案2】:

    在我的 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 中的许多其他任意值。我认为这是由于代码的线程不安全

    (示例:执行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;
    }
    

    【讨论】:

      猜你喜欢
      • 2010-12-16
      • 1970-01-01
      • 1970-01-01
      • 2011-12-05
      • 1970-01-01
      • 1970-01-01
      • 2016-08-09
      • 2011-03-20
      相关资源
      最近更新 更多