Как мне написать конкретный необработанный файловый дескриптор из 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");
}
}