Как мне написать конкретный необработанный файловый дескриптор из Rust?

Мне нужно написать в файловый дескриптор 3. Я искал его, но документация довольно плохая. Единственное, что я нашел, это использование libc библиотека и fdopen метод, но я не нашел ни одного примера о том, как его использовать или писать на нем.

Кто-нибудь может привести пример записи дескриптора файла в Rust?

2 ответа

Решение

Ты можешь использовать FromRawFd создать Fileиз определенного файлового дескриптора, но только в UNIX-подобных операционных системах:

use std::{
    fs::File,
    io::{self, Write},
    os::unix::io::FromRawFd,
};

fn main() -> io::Result<()> {
    let mut f = unsafe { File::from_raw_fd(3) };
    write!(&mut f, "Hello, world!")?;
    Ok(())
}
$ target/debug/example 3> /tmp/output
$ cat /tmp/output
Hello, world!

from_raw_fd небезопасно, потому что нет никакой гарантии, что дескриптор файла действителен или кто на самом деле отвечает за этот дескриптор файла.

Созданный File примет на себя владение файловым дескриптором: когда File выходит за рамки видимости, дескриптор файла будет закрыт. Вы можете избежать этого, используя либо IntoRawFd или же mem::forget,

Смотрите также:

libc crate - это "просто" библиотека-оболочка для взаимодействия между C и Rust, поэтому, чтобы узнать, как использовать функцию, следует прочитать руководство по функции C, для этого есть много источников, здесь один для fdopen():

fdopen() функция связывает поток с существующим файловым дескриптором, fd, Режим потока (одно из значений "r", "r+", "w", "w+", "a", "a+") должен быть совместим с режимом дескриптора файла. Индикатор положения файла нового потока установлен на принадлежащий fd и индикаторы ошибок и конца файла очищаются. Режимы "w" или же "w+" не вызывать усечение файла. Дескриптор файла не дублируется и будет закрыт, когда поток, созданный fdopen() закрыто. Результат применения fdopen() для общей памяти объекта не определено.

Основное использование так:

use libc::fdopen;
use std::ffi::CString;

fn main() {
    let mode = CString::new("w").unwrap();
    unsafe {
        let _ = fdopen(3, mode.as_ptr());
    }
}

Чтобы использовать его, вы можете использовать fwrite():

Функция fwrite() пишет nmemb элементы данных, каждый размер длиной в байты, к потоку, указанному потоком, получая их из местоположения, заданного ptr,

Итак, завершите пример:

use libc::{c_void, fdopen, fwrite};
use std::ffi::CString;

fn main() {
    let mode = CString::new("w").unwrap();
    let file = unsafe {
        let file = fdopen(3, mode.as_ptr());
        if file.is_null() {
            panic!("can't open file");
        }
        file
    };

    let welcome = "Hello world!";

    let result = unsafe { fwrite(welcome.as_ptr() as *const c_void, 1, welcome.len(), file) };
    if result != welcome.len() {
        panic!("write not successful");
    }
}
Другие вопросы по тегам