如何从 Rust 写入特定的原始文件描述符?
How do I write to a specific raw file descriptor from Rust?
我需要写入文件描述符 3。我一直在寻找它,但文档很差。我发现的唯一一件事是 libc
库和 fdopen
方法的使用,但我还没有找到任何关于如何使用它或在其上编写的示例。
谁能给我一个用 Rust 写入文件描述符的例子吗?
libc
crate 是 "just" C 和 Rust 之间接口的包装库,因此要了解如何使用函数,应该阅读 C 函数的手册,有很多来源那,这里是 fdopen()
:
The fdopen()
function associates a stream with the existing file descriptor, fd
. The mode of the stream (one of the values "r"
, "r+"
, "w"
, "w+"
, "a"
, "a+"
) must be compatible with the mode of the file descriptor. The file position indicator of the new stream is set to that belonging to fd
, and the error and end-of-file indicators are cleared. Modes "w"
or "w+"
do not cause truncation of the file. The file descriptor is not dup'ed, and will be closed when the stream created by fdopen()
is closed. The result of applying fdopen()
to a shared memory object is undefined.
基本使用是这样的:
use libc::fdopen;
use std::ffi::CString;
fn main() {
let mode = CString::new("w").unwrap();
unsafe {
let _ = fdopen(3, mode.as_ptr());
}
}
要使用它,您可以使用 fwrite()
:
The function fwrite()
writes nmemb
elements of data, each size bytes long, to the stream pointed to by stream, obtaining them from the location given by 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");
}
}
您可以使用来自特定文件描述符的 FromRawFd
to create a 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
or mem::forget
.
来避免这种情况
另请参阅:
- How can I read from a specific raw file descriptor in Rust?
我需要写入文件描述符 3。我一直在寻找它,但文档很差。我发现的唯一一件事是 libc
库和 fdopen
方法的使用,但我还没有找到任何关于如何使用它或在其上编写的示例。
谁能给我一个用 Rust 写入文件描述符的例子吗?
libc
crate 是 "just" C 和 Rust 之间接口的包装库,因此要了解如何使用函数,应该阅读 C 函数的手册,有很多来源那,这里是 fdopen()
:
The
fdopen()
function associates a stream with the existing file descriptor,fd
. The mode of the stream (one of the values"r"
,"r+"
,"w"
,"w+"
,"a"
,"a+"
) must be compatible with the mode of the file descriptor. The file position indicator of the new stream is set to that belonging tofd
, and the error and end-of-file indicators are cleared. Modes"w"
or"w+"
do not cause truncation of the file. The file descriptor is not dup'ed, and will be closed when the stream created byfdopen()
is closed. The result of applyingfdopen()
to a shared memory object is undefined.
基本使用是这样的:
use libc::fdopen;
use std::ffi::CString;
fn main() {
let mode = CString::new("w").unwrap();
unsafe {
let _ = fdopen(3, mode.as_ptr());
}
}
要使用它,您可以使用 fwrite()
:
The function
fwrite()
writesnmemb
elements of data, each size bytes long, to the stream pointed to by stream, obtaining them from the location given byptr
.
所以,完整的例子:
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");
}
}
您可以使用来自特定文件描述符的 FromRawFd
to create a 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
or mem::forget
.
另请参阅:
- How can I read from a specific raw file descriptor in Rust?