BufReader из необработанного fd - PullRequest
1 голос
/ 23 апреля 2019

Я использую 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, который не реализует Read, необходимый для BufRead.

Какие-либо предложения относительно того, как я мог бы получить BufReader из raw fd, не делая mio небезопасным для использования?

Кстати, файловые дескрипторы не являются файлами (хотя они могут быть в какой-то момент), поэтому я не могу использовать File::, сейчас я просто отправляю клиентский stdin в виде необработанного fd через fdpass.

1 Ответ

2 голосов
/ 23 апреля 2019

К сожалению, FromRawFd реализован только для руки, полной структур . Вам нужно заранее знать, какой «файл» вы хотите прочитать, или вы рискуете неопределенным поведением поведения (потому что 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(())
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...