简体   繁体   English

从Linux的管道/套接字中读取所有内容还是全部内容?

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

I've got a subprocess that I've popened that outputs fixed-sized structs containing some status information. 我弹出了一个子进程,该子进程输出包含某些状态信息的固定大小的结构。 My plan is to have a separate thread that reads from the stdout of that process to pull in the data as it comes. 我的计划是要有一个单独的线程,该线程从该进程的标准输出中读取数据,以将其引入。

I've got to check a flag periodically to make sure the program is still running so I can shut down cleanly, so I have to set the pipe to non-blocking and just have to run a loop piecing together the status message. 我必须定期检查一个标志以确保程序仍在运行,以便可以干净地关闭,因此我必须将管道设置为非阻塞状态,而只需要运行将状态消息拼凑在一起的循环即可。

Is there a canonical way I can tell Linux "either read this entire amount or nothing before a timeout", that way I'll be able to check my flag, but I don't have to handle the boilerplate of reading the structure piece meal? 有没有一种规范的方法可以告诉Linux“要么在超时之前读取全部数据,要么什么都不读取”,那样我就可以检查我的标志,但是不必处理读取结构块的样板?

Alternatively, is there a way to push data back into a pipe? 或者,是否有办法将数据推回到管道中? I could try to read the whole thing, and if it times out before it's all ready, push what I have back in and try again in a bit. 我可以尝试阅读整个内容,如果在准备就绪之前超时,则将我的内容推回去,然后再试一次。

I've also written my popen (so I can grab stdin and stdout, so I'm totally OK using a socket rather than a pipe if that helps). 我也写了我的popen(这样我就可以抓取stdin和stdout,所以如果可以的话,我完全可以使用套接字而不是管道)。

Here's what I ended up doing for anyone that's curious. 这就是我最终对任何有好奇心的人所做的事情。 I just wrote a class that wraps up the file descriptor and message size and gives me the "all-or-none" behavior I want. 我只是写了一个包装文件描述符和消息大小的类,并提供了我想要的“全有或全无”行为。

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_;
    };

Which can then be used something like this: 然后可以使用像这样的东西:

    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>
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM