【问题标题】:How do I write to a specific raw file descriptor from Rust?如何从 Rust 写入特定的原始文件描述符?
【发布时间】:2019-02-25 00:32:31
【问题描述】:

我需要写入文件描述符 3。我一直在寻找它,但文档很差。我唯一发现的是libc库和fdopen方法的使用,但是我没有找到任何关于如何使用它或在上面写的例子。

谁能给我一个在 Rust 中写入文件描述符的示例?

【问题讨论】:

  • crates.io 上有几个 crate。你试过了吗?

标签: unix io rust file-descriptor


【解决方案1】:

您可以使用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。
  • @rodrigo 是的,或者mem::forget
  • @Shepmaster: mem::forget 会起作用,但我认为如果你想让 fd 保持打开状态,仅仅因为它在你到达时已经打开,那么 into_raw_fd()是正确的方法:mem::forget 可能会产生其他不良影响,例如不释放内部缓冲区或谁知道。
【解决方案2】:

libc crate “只是”一个用于 C 和 Rust 之间接口的包装库,所以要知道如何使用函数,应该阅读 C 函数的手册,有很多来源,这里有一个 @ 987654321@:

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数据元素写入stream指向的流,从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");
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-20
    • 1970-01-01
    • 2011-08-16
    • 1970-01-01
    • 2017-09-05
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多