正确的代码 - 非阻塞管与POPEN(Correct Code - Non-blocking pip

2019-06-25 09:49发布

有吨的约非阻塞管道的问题,但也有代码,可以被复制和粘贴NO实例(少校正)和使用。

我从这个线程的想法和来源: 采用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);

Answer 1:

是。 如果read与误差值(调用返回-1 ),并 errno设置为EAGAIN ,这意味着没有数据可用,所以你continue循环再试一次。 如果你摆脱了的errno ,错误都会被有效忽略,你的程序可能会崩溃。 试想一下,如果你没有将其删除:当read返回-1 ,但是,说错误是,管道被打破(另一端关闭了它),你只需继续努力,以循环并进入一个无限循环。 馊主意。



Answer 2:

在我的Linux多线程应用程序(Ubuntu的16.04,x86_64的,本机POSIX线程,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;
}


文章来源: Correct Code - Non-blocking pipe with popen
标签: c++ pipe popen