从 Linux 中的管道/套接字读取所有结构或什么都没有

Reading all of a stuct or nothing from a pipe/socket in linux?

本文关键字:结构 什么 读取 Linux 管道 套接字      更新时间:2023-10-16
我有一个子

进程,我打开了它输出包含一些状态信息的固定大小的结构。 我的计划是有一个单独的线程,从该过程的 stdout 读取数据,以便在数据到来时提取数据。

我必须定期检查一个标志以确保程序仍在运行,以便我可以干净地关闭,所以我必须将管道设置为非阻塞,并且只需要运行一个将状态消息拼凑在一起的循环。

有没有一种规范的方法可以告诉 Linux"要么在超时之前读取全部内容,要么什么都不读取",这样我就可以检查我的标志,但我不必处理阅读结构零碎的样板?

或者,有没有办法将数据推送回管道? 我可以尝试阅读整个内容,如果它在一切准备就绪之前超时,请将我所拥有的内容推回去,然后再试一次。

我还编写了我的 popen(所以我可以抓取 stdin 和 stdout,所以如果有帮助,我完全可以使用套接字而不是管道)。

这是我最终为任何好奇的人所做的。 我刚刚编写了一个类,它包装了文件描述符和消息大小,并给了我想要的"全有或全无"行为。

struct aonreader { 
    aonreader(int fd, ssize_t size) { 
        fd_      = fd;
        size_    = size_;
        nread_   = 0;
        nremain_ = size_;
    }
    ssize_t read(void *dst) { 
         ssize_t ngot = read(fd, (char*)dst + nread_, nremain_);
         if (ngot < 0) { 
             if (errno != EAGAIN && errno != EWOULDBLOCK) {
                  return -1; // error
             }
         } else {
             nread_   += ngot;
             nremain_ -= ngot;
             // if we read a whole struct
             if (nremain_ == 0) {
                 nread_   = 0;
                 nremain_ = size_;
                 return size_;
             }
         }
         return 0;             
    private:
         int     fd_;
         ssize_t size_;
         ssize_t nread_;
         ssize_t nremain_;
    };

然后可以使用这样的东西:

    thing_you_want thing;
    aonreader buffer(fd, sizeof(thing_you_want));
    while (running) { 
        size_t ngot = buffer.read(&thing);
        if (ngot == sizeof(thing_you_want)) { 
            <handle thing>
        } else if (ngot < 0) { 
            <error, handle errno>
        }
        <otherwise loop and check running flag>
    }