我正在使用fdpass crate通过unix套接字将文件描述符从一个进程发送到另一个进程(我不在乎兼容性,仅unix可以)。
使用mio,我设法监听那些文件描述符上的事件:
let fd = fdpass::recv_fd(&mut client, vec!(0u8)).unwrap();
let efd = EventedFd(&fd.into_raw_fd());
poll.register(&efd, Token(0), Ready::readable(), PollOpt::level()).unwrap();
这很好用,但是我想使用BufReader
逐行读取该文件描述符。我一直在尝试找出一种在无法成功实现from_raw_fd()
的东西上使用BufReader
的方法。它似乎仅存在于文件或网络流之类的东西中。唯一的另一件事是Stdio
并没有实现BufRead
所需的读取。
关于如何从原始fd中获取BufReader
而又不使mio不安全使用的任何建议?
顺便说一下,文件描述符不是文件(尽管有时可能不是文件),所以我不能使用File::
,现在我只是通过fdpass将客户端的stdin作为原始fd发送。
答案 0 :(得分:2)
不幸的是,FromRawFd
仅适用于hand full of structs。您需要事先知道要读取哪种“文件”,否则可能会面临不确定的行为(因为Rust认为FD是不是这种类型的文件)。
但是,您可以实现自己的结构,除了读取对所有文件描述符都适用之外,它什么都不做。这可以通过对man (2) read
的函数调用来完成。
use libc;
use std::ffi::OsStr;
use std::io::{Error, Read, Result};
use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::{FromRawFd, RawFd};
pub struct RawFdReader {
fd: RawFd,
}
impl FromRawFd for RawFdReader {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
Self { fd }
}
}
impl Read for RawFdReader {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
assert!(buf.len() <= isize::max_value() as usize);
match unsafe { libc::read(self.fd, buf.as_mut_ptr() as _, buf.len()) } {
x if x < 0 => Err(Error::last_os_error()),
x => Ok(x as usize),
}
}
}
fn main() -> Result<()> {
let mut reader = unsafe { RawFdReader::from_raw_fd(0) };
let mut buffer = vec![0; 10];
let len = reader.read(&mut buffer)?;
println!("{:?}", OsStr::from_bytes(&buffer[..len]));
Ok(())
}