将同步 Rust IO 驱动程序转换为 `async`
Posted
技术标签:
【中文标题】将同步 Rust IO 驱动程序转换为 `async`【英文标题】:Converting a synchronous Rust IO driver to be `async` 【发布时间】:2020-12-07 11:15:36 【问题描述】:我有一个UIO driver,它在所谓的wait_on_complete
函数中轮询文件描述符以等待中断。这是完全同步的,所以会阻塞(有超时)。我想迁移代码,使wait_on_complete
是async
(或者可以轻松包装以创建有用的Future
),但我不确定最好的策略。
我对选项的看法是:
-
使用
mio::Poll
,据我了解,这意味着使用 Tokio 反应器,但我无法在 Tokio ^0.3 中遵循此 API。在 Tokio 0.2 中似乎有一个 few things around 这个,但它们已经消失了(尽管它似乎仍然在代码中 - 这只是缺少文档吗?)。
使用 polling
之类的东西,它带有自己的反应器。问题在于驱动程序似乎放错了反应堆的位置。
在自己的线程中运行同步代码并与async
通道通信。鉴于async
的要点之一是正确集成异步 IO,这在架构上似乎是一个糟糕的选择(实际上,IO 非常适合主状态机)。
还有一些我不知道的事情。
(1) 似乎是显而易见的解决方案,但我并不完全清楚如何去做。是否有一些关于创建自己的mio
设备并在 Tokio 运行时中使用它的最新文档?
还有没有其他方法可以让我做我想做的事?我是否在考虑中遗漏了什么?
【问题讨论】:
大多数运行时都有一种方法来处理阻塞任务,方法是在单独的线程上运行它们。见tokio::spawn_blocking
@IbraheemAhmed 谢谢,我知道(这是我列表中 (3) 的假定机制)。
【参考方案1】:
使用来自async-io
的Async
很容易做到这一点。
制作一个封装你的fd
的结构,为它实现AsRawFd
,然后用Async
包装它。
这允许您使用read_with
和write_with
执行自定义异步操作。
【讨论】:
这个看起来和Tokio approach很相似,我后来了解到的是当前的 Tokio 策略。async-io
的情况下反应堆在哪里运行? (例如,它是否以某种方式依赖于运行时?)
Async
上有一个文档段落:“但是,不要将 Async 与 File、Stdin、Stdout 或 Stderr 等类型一起使用,因为所有操作系统在进入非阻塞模式时都会出现问题。”
async-io
产生自己的反应器线程,因此它不依赖于特定的运行时/执行器。它本身也是用于async-std
的反应器。
如果您的 fd 是您使用 open()
从 UIO 设备获得的,那应该没问题。文件的问题在于将数据存储在文件系统上的“真实”文件。
只是为了未来读者的完整性:Tokio 对反应器采用了不同的方法,因为它在执行程序线程中运行。哪个更好取决于用例。以上是关于将同步 Rust IO 驱动程序转换为 `async`的主要内容,如果未能解决你的问题,请参考以下文章
Rust, 替换 crates.io 为国内镜像站 crates.cn
是否可以将字节解码为 UTF-8,将错误转换为 Rust 中的转义序列?