前言:
在现代软件开发中,性能和效率是衡量应用成功的关键指标。Rust 语言以其安全性、速度和内存管理能力而闻名,而 Mio 库则是 Rust 生态系统中的一颗璀璨明珠,专为追求极致性能的开发者设计。本文将带您深入了解 Mio,一个专注于非阻塞 API 和事件通知的低层次 I/O 库,探索如何利用它构建高性能的 I/O 应用程序。
解锁 Rust 异步编程:深入探索 Mio 库的高效 I/O 之道
Mio 是 Rust 的一个快速、低层次的 I/O 库,专注于非阻塞 API 和事件通知,用于构建尽可能减少操作系统抽象开销的高性能 I/O 应用程序。
API 文档
v1[1] v0.8[2]
这是一个低层次库,如果您正在寻找更易于上手的东西,请看 Tokio[3]。
使用方法
要使用 mio
,请先将其添加到您的 Cargo.toml
中:
[dependencies]
mio = "1"
接下来,我们可以开始使用 Mio。以下是使用 TcpListener
和 TcpStream
的快速介绍。注意,此示例必须指定 features = ["os-poll", "net"]
。
use std::error::Error;
use mio::net::{TcpListener, TcpStream};
use mio::{Events, Interest, Poll, Token};
// 一些令牌,以便我们识别哪个事件对应哪个套接字。
const SERVER: Token = Token(0);
const CLIENT: Token = Token(1);
fn main() -> Result<(), Box<dyn Error>> {
// 创建一个轮询实例。
let mut poll = Poll::new()?;
// 为事件创建存储空间。
let mut events = Events::with_capacity(128);
// 设置服务器套接字。
let addr = "127.0.0.1:13265".parse()?;
let mut server = TcpListener::bind(addr)?;
// 开始监听传入连接。
poll.registry()
.register(&mut server, SERVER, Interest::READABLE)?;
// 设置客户端套接字。
let mut client = TcpStream::connect(addr)?;
// 注册套接字。
poll.registry()
.register(&mut client, CLIENT, Interest::READABLE | Interest::WRITABLE)?;
// 开始事件循环。
loop {
// 轮询 Mio 事件,阻塞直到我们收到一个事件。
poll.poll(&mut events, None)?;
// 处理每个事件。
for event in events.iter() {
// 我们可以使用我们之前提供给 `register` 的令牌来确定事件是针对哪个套接字。
match event.token() {
SERVER => {
// 如果这是服务器的事件,这意味着连接已经准备好被接受。
//
// 接受连接并立即丢弃。这将关闭套接字并通知客户端 EOF。
let connection = server.accept();
drop(connection);
}
CLIENT => {
if event.is_writable() {
// 我们可以(可能)在不阻塞的情况下写入套接字。
}
if event.is_readable() {
// 我们可以(可能)在不阻塞的情况下从套接字读取。
}
// 由于服务器刚刚关闭了连接,让我们从事件循环中退出。
return Ok(());
}
// 我们不期望任何除了我们提供的令牌之外的事件。
_ => unreachable!(),
}
}
}
}
特性
非阻塞 TCP、UDP、UDS 由 epoll、kqueue 和 IOCP 支持的 I/O 事件队列 运行时零分配 平台特定的扩展
非目标
以下是明确从 Mio 中省略的,留给用户或更高层次的库。
文件操作 线程池 / 多线程事件循环 计时器
平台
当前支持的平台:
Android(API 级别 21) DragonFly BSD FreeBSD Linux NetBSD OpenBSD Windows iOS macOS
Mio 可以处理与上述平台的事件系统的接口。它们的实现细节在 API 文档中的 Poll
类型中进一步讨论(见上文)。
Mio 通常支持与 Rust 语言(rustc)相同的上述平台版本,除非另有说明。
Windows 用于轮询套接字的实现使用的是 [wepoll] 策略。这使用 Windows AFD 系统访问套接字就绪事件。
不支持
Wine,见 问题 #1444
MSRV 政策
MSRV(最小支持的 Rust 版本)对于给定的小版本(1.x)是固定的。然而,在提升小版本时可以增加 MSRV,例如从 1.0 升级到 1.1 允许我们增加 MSRV。无法增加 Rust 版本的用户可以使用旧的小版本。以下是 Mio 版本及其 MSRV 的列表:
v0.8: Rust 1.46。 v1.0: Rust 1.70。
但请注意,Mio 也有依赖项,它们可能有不同的 MSRV 政策。我们尝试在更新依赖项时坚持上述政策,但这并不总是可能的。
不支持的标志
Mio 使用不同的实现来支持相同的功能,这取决于平台。Mio 通常使用“最佳”实现,其中“最佳”通常意味着对 Mio 的用例最有效。然而,这意味着实现通常是特定于有限数量的平台,这意味着我们经常有多个实现相同的功能。在某些情况下,可能需要不使用“最佳”实现,而是 Mio 支持的另一种实现(在其他平台上)。Mio 官方不支持平台上的次要实现,但我们确实有各种 cfg 标志来强制使用这些情况下的另一种实现。
当前标志:
mio_unsupported_force_poll_poll
,使用基于poll(2)
的实现为mio::Poll
。mio_unsupported_force_waker_pipe
,使用基于pipe(2)
的实现为mio::Waker
。
再次强调,Mio 官方不支持这一点。此外,这些标志将来可能会消失。
社区
一群 Mio 用户在 [Discord] 上闲逛,这可能是提问的好地方。也可以在 GitHub 上打开新问题 来提问、报告错误或建议新功能。
v1: https://docs.rs/mio/^1
[2]v0.8: https://docs.rs/mio/^0.8
[3]Tokio: https://tokio.rs