[英]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.