不灭的火

革命尚未成功,同志仍须努力:加密SHA/AES/RSA下载JDK17

作者:AlbertWen  添加时间:2025-09-07 15:50:31  修改时间:2025-09-11 04:54:49  分类:21.Rust编程  编辑

Rust 异步运行时(Async Runtime)是一个在 Rust 程序主逻辑(main 函数)开始执行之前和之后,负责为其提供关键执行环境的代码库和一组服务。

它的核心任务是管理异步任务(如 async/.await)所需的复杂调度、上下文切换和事件驱动I/O。

一、什么是异步运行时?

它不是一个单一的东西,而是一个由多个组件构成的生态系统,专门用于驱动异步代码。

1、核心组件包括: 

  • 【组件1】执行器(Executor)

职责

就像一个公司的“项目经理”。它 持有/管理 一个或多个(线程池),并从任务队列中取出准备好异步任务(Future),放到线程上执行。一个Future在无法立即取得进展时(比如等待网络数据),会被挂起,执行器就会去执行下一个任务。

工作原理

(1) 你通过 #[tokio::main] 等方式将 main 函数交给运行时,或者手动将 Future 塞给执行器(例如 tokio::spawn(...))。

(2) 执行器在其线程上不停地轮询(poll) 它管理的所有 Future。—— 备注:轮询任务队列中的Future

(3) 当一个 Future 被轮询并返回 Poll::Pending 时,执行器就知道这个 Future 在等待外部事件(如网络数据包、定时器到期),于是它先把这个 Future 挂起,转而去轮询其他可以继续执行的 Future。

(4) 当反应器通知执行器“某个事件准备好了”(比如网络数据到了),执行器会找到正在等待这个事件的 Future,并再次轮询它,这次它很可能就会返回 Poll::Ready 

 

  •  【组件2】反应器/事件循环(Reactor/Event Loop)

职责

就像公司的“前台”或“调度中心”。它利用操作系统提供的机制,与操作系统的异步接口交互(如:Linux的epoll,MacOS的kquue,Windows的IOCP)。监听和收集各种I/O事件(例如“这个Socket有数据可读了”、“那个文件写入完成了”、“那个定时器到期了”等)。当事件发生时,它会通知对应的Waker。

工作原理

(1) 它向操作系统注册需要监听的事件和其对应的唤醒机制(Waker)。

(2) 它阻塞地等待操作系统发出事件通知。

(3) 当事件发生时,它通知执行器:“嘿,你之前关心的那个事件发生了,可以去重新轮询等待它的那个 Future 了!”

 

  •  【组件3】Waker(连接执行器和反应器的桥梁)

每个异步任务都有一个关联的 Waker。当一个任务因为等待 I/O 而阻塞时,它会将自己的 Waker 注册到反应器上。当反应器检测到该任务等待的事件就绪时(例如数据到达),就会调用 Waker 的 wake() 方法。这个方法的作用就是告诉执行器:“嘿,这个任务之前等的东西准备好了,可以重新把它放进队列里执行了!”

备注:这是异步运行时中一个非常精巧的设计。当一个 Future 返回 Poll::Pending 时,它会附上一个 Waker 对象。反应器在事件发生时,会调用与这个事件关联的 Waker 的 wake() 方法。这个方法会通知执行器:“喂,那个之前挂起的 Future 现在可能有进展了,快再来轮询它一下!(所谓的轮询,就是再次查看一下任务的准备状态是否为Poll::Ready)” 这样就避免了执行器盲目地、不停地轮询所有 Future,极大地提高了效率。

2、常见的选择

Rust 标准库提供了定义异步操作的接口(如 Future trait),但没有提供具体的运行时实现。这意味着你需要选择一个第三方库来充当运行时:

  • Tokio:最流行、功能最全面的运行时,提供了高性能的网络、文件系统、定时器等。
  • async-std:旨在提供与标准库类似 API 风格的异步运行时。
  • smol: 一个非常小巧且高效的运行时。

当你写 #[tokio::main] 时,你就是在明确选择并使用 Tokio 运行时。 这个宏会将你的普通 main 函数转换为一个由 Tokio 运行时驱动的异步入口点。

二、异步编程的基础:async/.await 和 Future

首先,你需要明白 Rust 语言本身只提供了最基础的异步编程工具,而不是一个完整的运行时:

  • async: 将一个代码块标记为异步的。当你写 async fn foo() {...} 时,这个函数并不会直接执行,而是返回一个实现了 Future trait 的对象。
  • Future: 这是一个核心 trait,它代表一个可能尚未完成的异步计算。它有一个核心方法:poll(轮询)。poll 方法会检查这个计算是否完成:
    • 如果完成了,就返回 Poll::Ready(结果)
    • 如果没完成,就返回 Poll::Pending,并且安排好在未来某个时间点(当它可能准备好时),需要再次被“问一下”(即再次调用 poll)。
  • .await: 在 async 函数内部,你可以在一个 Future 上使用 .await。这相当于厨师看到点菜单上写着“等水烧开”,他就把这张单子先放下,先去处理别的单子。.await 就是一个让出控制权的点。

 

关键点:Rust 标准库只定义了 Future 这个接口和 async/.await 语法,但并没有提供驱动(轮询)这些 Future 的机制。这个驱动机制,就是异步运行时的职责。