如何在Rust中向特定的原始文件描述符写入数据?

8

我需要写入文件描述符3。我一直在搜索,但是文档相当贫乏。 我唯一找到的是使用libc库和fdopen方法,但是我没有找到任何关于如何使用它或者向其写入的示例。

有人能提供一个在Rust中写入文件描述符的示例吗?


1
crates.io 上有几个板条箱。你试过它们中的任何一个吗? - Peter Hall
2个回答

14

您可以使用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 超出作用域时,文件描述符将被关闭。可以通过使用 IntoRawFdmem::forget 来避免这种情况发生。

另请参见:


这个非常好用!!真的是一个简单而干净的解决方案! - rdiaz82
值得一提的是,如果您不想在f被丢弃时关闭_fd_,您可以调用f.into_raw_fd()(从trait IntoRawFd)并丢弃返回值,它将只是3 - rodrigo
1
@rodrigo 是的,或者 mem::forget - Shepmaster
3
@Shepmaster: mem::forget 可以工作,但我认为如果您想保持_fd_ 打开状态,仅因为在您到达时已经打开它,则 into_raw_fd() 是正确的方法:mem::forget 可能会有其他不希望发生的影响,例如不释放内部缓冲区或谁知道什么。 - rodrigo

3

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()函数从指针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");
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接