我需要写入文件描述符3。我一直在搜索,但是文档相当贫乏。 我唯一找到的是使用libc
库和fdopen
方法,但是我没有找到任何关于如何使用它或者向其写入的示例。
有人能提供一个在Rust中写入文件描述符的示例吗?
我需要写入文件描述符3。我一直在搜索,但是文档相当贫乏。 我唯一找到的是使用libc
库和fdopen
方法,但是我没有找到任何关于如何使用它或者向其写入的示例。
有人能提供一个在Rust中写入文件描述符的示例吗?
您可以使用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
来避免这种情况发生。
另请参见:
f
被丢弃时关闭_fd_,您可以调用f.into_raw_fd()
(从trait IntoRawFd
)并丢弃返回值,它将只是3
。 - rodrigomem::forget
。 - Shepmastermem::forget
可以工作,但我认为如果您想保持_fd_ 打开状态,仅因为在您到达时已经打开它,则 into_raw_fd()
是正确的方法:mem::forget
可能会有其他不希望发生的影响,例如不释放内部缓冲区或谁知道什么。 - rodrigolibc
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()
函数从指针ptr
所指向的位置获取nmemb
个元素,每个元素的大小为size
字节,然后将其写入到流stream
中。
因此,完整示例代码如下:
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");
}
}