50 个版本 (15 个稳定版)
2.0.3 | 2023 年 12 月 1 日 |
---|---|
2.0.2 | 2023 年 6 月 30 日 |
1.1.0-pre.0 | 2023 年 5 月 24 日 |
1.0.9 | 2023 年 3 月 20 日 |
0.2.0 | 2021 年 6 月 24 日 |
#12 in Operating systems
3,539,447 个月下载量
在 3,733 个crate中使用 (26 个直接使用)
63KB
805 行代码,不包括注释
此库引入了 OwnedFd
、BorrowedFd
以及支持的类型和特质,以及针对 Windows 的相应功能,实现了安全的所有权和借用 I/O 生命周期模式。
这与 RFC 3128(I/O 安全性 RFC)相关,该 RFC 已合并。现在正在进行将此处开发的 OwnedFd
和 BorrowedFd
类型以及 AsFd
特质移动到 std
的工作。
要快速了解,请查看代码示例
- hello,这是此 API 的基本演示,手动进行低级 I/O,使用提供的示例 FFI 绑定
- easy-conversions,展示了将
from_into
便利功能从impl Into*
转换为impl From*
的便利功能。 - portable-views,展示了允许将文件描述符临时“查看”为任何拥有类型(如
File
)的便利功能。 - flexible-apis,展示了如何编写接受无类型 I/O 资源的库 API。
- owning-wrapper,展示了如何实现一个包装
Owned*
类型的类型。
API 的核心非常简单,由两个主要类型和三个主要特质组成
pub struct BorrowedFd<'fd> { ... }
pub struct OwnedFd { ... }
pub trait AsFd { ... }
pub trait IntoFd { ... }
pub trait FromFd { ... }
impl AsRawFd for BorrowedFd<'_> { ... }
impl AsRawFd for OwnedFd { ... }
impl IntoRawFd for OwnedFd { ... }
impl FromRawFd for OwnedFd { ... }
impl Drop for OwnedFd { ... }
impl AsFd for BorrowedFd<'_> { ... }
impl AsFd for OwnedFd { ... }
impl IntoFd for OwnedFd { ... }
impl FromFd for OwnedFd { ... }
在Windows上,每个Fd
对象都有对应的Handle
和Socket
版本,还有一个特殊的HandleOrInvalid
类型来处理Windows API中的不一致错误报告。
透明的魔法
这里是有趣的部份。BorrowedFd
和OwnedFd
是repr(transparent)
的,并持有RawFd
值,而Option<BorrowedFd>
和Option<OwnedFd>
在Rust >= 1.63中是FFI安全的,因此它们都可以在FFI直接使用。
extern "C" {
pub fn open(pathname: *const c_char, flags: c_int, ...) -> Option<OwnedFd>;
pub fn read(fd: BorrowedFd<'_>, ptr: *mut c_void, size: size_t) -> ssize_t;
pub fn write(fd: BorrowedFd<'_>, ptr: *const c_void, size: size_t) -> ssize_t;
pub fn close(fd: OwnedFd) -> c_int;
}
有了这样的绑定,用户永远不需要触摸RawFd
值。当然,不是所有的代码都会这样做,但这对能够这样做的代码来说是一个有趣的功能。这就是为什么要使用BorrowedFd
而不是仅仅使用&OwnedFd
的原因。
注意open
函数使用Option<OwnedFd>
作为返回值,表示它可能成功或失败。
Rust中的I/O安全性
I/O安全性特性在Rust 1.63中得到稳定。从这个版本开始或更高版本,io-lifetimes将使用并重新导出标准库中的类型和特性。在较旧版本中,io-lifetimes定义了自己的这些类型和特性的副本。
io-lifetimes还包括一些不在std中的特性,包括可移植特性AsFilelike
/AsSocketlike
等,From特性中的
from_into_
函数,以及视图。
现有技术
有几个类似的crate:fd、filedesc、filedescriptor、owned-fd和unsafe-io。
其中一些提供了额外的功能,例如创建管道或套接字、获取和设置标志以及执行读写操作。io-lifetimes省略了这些功能,将它们作为单独的层提供。
大多数这些crate都提供了复制文件描述符的方法。io-lifetimes目前将其视为可以由上层提供的另一个功能,尽管如果存在这种操作是常见用例的情况,它也可以添加。
io-lifetimes的显著特点是它使用repr(transparent)
来支持直接FFI使用,狭窄的优化使得Option
也能支持直接FFI使用(在Rust >= 1.63中),生命周期感知的As
/Into
/From
特性,它们利用Rust的生命周期系统,并允许安全的和经过检查的from_
和as_
/into_
函数,以及由其底层安全性提供的强大便捷功能。
io-lifetimes还完全支持Windows,以及Unix/Windows的可移植抽象,涵盖文件类和套接字类类型。
io-lifetimes 的 OwnedFd
类型与 fd 的 FileDesc
类似。io-lifetimes 没有使用 close_on_drop
参数,而是使用 OwnedFd
和 BorrowedFd
来分别表示释放和非释放句柄,这种方式在编译时而不是运行时进行检查。
io-lifetimes 的 OwnedFd
类型也与 filedesc 的 FileDesc
类似。io-lifetimes 的 OwnedFd
保留了值 -1,因此在它的 Drop
中不需要测试 -1
,并且 Option<OwnedFd>
(在 Rust >= 1.63)与 FileDesc
大小相同。
io-lifetimes 的 OwnedFd
类型也与 owned-fd 的 OwnedFd
类似。io-lifetimes 没有实现 Clone
,因为由于操作系统进程限制,复制文件描述符可能会失败,而 Clone
是一个不可失败接口。
io-lifetimes 的 BorrowedFd
与 owned-fd 的 FdRef
类似,但它使用生命周期参数和 PhantomData
而不是将原始文件描述符值转换为引用值。
io-lifetimes 的便利特性与 unsafe-io 类似,但 io-lifetimes 是基于它自己的 As*
/Into*
/From*
特性构建的,而不是通过 OwnsRaw
扩展 AsRaw*
/IntoRaw*
/FromRaw*
,因此它们更简单、更安全。io-lifetimes 不包括 unsafe-io 的 *ReadWrite*
或 *HandleOrSocket*
抽象,并将这些作为由上层单独提供的特性。
支持的最小 Rust 版本 (MSRV)
此软件包目前适用于 [Debian 稳定版上的 Rust],目前是 Rust 1.63。此策略可能在未来的小版本发布中改变,因此使用固定版本 Rust 的用户应将此软件包的版本锁定为特定版本。
依赖项
~0–12MB
~128K SLoC