将同步 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_completeasync(或者可以轻松包装以创建有用的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-ioAsync 很容易做到这一点。

制作一个封装你的fd 的结构,为它实现AsRawFd,然后用Async 包装它。

这允许您使用read_withwrite_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

如何使用Async&Await将同步代码转换为异步编程

是否可以将字节解码为 UTF-8,将错误转换为 Rust 中的转义序列?

如何将 C 字符串转换为 Rust 字符串并通过 FFI 转换回来?

如何将 C 变长数组代码转换为 Rust?

将 Vec<String> 转换为 Rust 中的 &str 切片?