编者注:这个问题适用于1.0之前的Rust版本。一些答案已经更新,以涵盖Rust 1.0或更高版本,但不是全部。
我在Rust中编写了一个systemd socket激活服务。我的进程被systemd传递给一个打开的文件描述符。
是否有任何Rust IO函数采用原始文件描述符?
我在Rust 1.0之前每晚使用Rust。
我认为现在你最好的选择可能是使用libc crate来处理原始文件描述符。
FileDesc
移动到私人范围是几个月前从运行时删除的影响。有关更多背景信息,请参阅此RFC。 std::os::unix
目前的类型为Fd
,我认为长期的想法是在该模块中公开更多特定于平台的功能。
从Rust 1.1开始,您可以使用FromRawFd
从特定文件描述符创建File
,但仅限于类UNIX操作系统:
use std::{
fs::File,
io::{self, Read},
os::unix::io::FromRawFd,
};
fn main() -> io::Result<()> {
let mut f = unsafe { File::from_raw_fd(3) };
let mut input = String::new();
f.read_to_string(&mut input)?;
println!("I read: {}", input);
Ok(())
}
$ cat /tmp/output
Hello, world!
$ target/debug/example 3< /tmp/output
I read: Hello, world!
from_raw_fd
不安全:
此函数也不安全,因为当前返回的基元具有它们是它们包装的文件描述符的唯一所有者的契约。使用此函数可能会意外地违反此合同,这可能会导致依赖于此操作的代码中的内存不安全。
创建的File
将承担文件描述符的所有权:当File
超出范围时,文件描述符将被关闭。您可以使用IntoRawFd
或mem::forget
来避免这种情况。
也可以看看:
编者注:这个答案适用于1.0之前的Rust版本,不能在Rust 1.0中编译。
我只是自己探索生锈,但经过一番搜索后,想出了以下native
箱子的使用方法:(使用文件描述符“1”作为示例 - 1是stdout
)
extern crate native;
use native::io::file::FileDesc as FileDesc;
fn main()
{
let mut f = FileDesc::new(1, true);
let buf = "Hello, world!\n".as_bytes();
f.inner_write(buf);
}
(使用rustc 0.13.0-nightly
测试。请注意,inner_write
方法可能已在更新版本的write
中重命名为libstd
)
native
crate最近从标准库和FileDesc
中删除,但仍然存在,因为std::sys::fs::FileDesc
不再公开...