核心组件
┌─────────────────────────────────────────────────────────────┐
│ 用户代码 │
├─────────────────────────────────────────────────────────────┤
│ Runtime (运行时) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Task │ │ Group │ │ Synchronization │ │
│ │ Scheduler │ │ (结构化并发)│ │ Primitives │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Coroutines (协程层) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Context │ │ Stack │ │ StackPool │ │
│ │ Switching │ │ Management │ │ (栈池) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Event Loop (事件循环) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ io_uring │ │ epoll │ │ kqueue │ │
│ │ (Linux) │ │ (Linux) │ │ (macOS/BSD) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ IOCP │ │ poll │ │
│ │ (Windows) │ │ (fallback) │ │
│ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ OS Layer (操作系统层) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Linux │ │ Windows │ │ macOS │ │
│ │ (posix) │ │ (win32) │ │ (bsd) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
2.1.1 组件说明 #
Runtime(运行时) #
运行时是用户代码的主要入口点,提供:
- 任务调度:自动在协程之间切换
- I/O 集成:将 I/O 操作与事件循环关联
- 同步原语:协程感知的锁和通道
Coroutines(协程层) #
底层协程实现:
- Context Switching:用户态上下文切换
- Stack Management:可增长的协程栈
- StackPool:栈复用以减少分配开销
Event Loop(事件循环) #
基于完成的事件循环:
- Backend Abstraction:统一的异步 I/O 接口
- Completion-based:操作完成后回调
- ThreadPool:用于模拟异步文件 I/O
OS Layer(操作系统层) #
平台特定代码:
- 系统调用封装
- 平台特定的 I/O 操作
- 线程和进程管理
2.1.2 设计原则 #
1. 用户态协程 #
无需编译器支持,在用户空间实现协程切换。优点:
- 完全控制调度
- 无隐藏的内存分配
- 可预测的性能
2. 结构化并发 #
所有子任务必须在父任务范围内完成:
- 防止任务泄漏
- 简化错误处理
- 明确的生命周期
3. 零成本抽象 #
与手写状态机相比,协程不会引入额外开销:
- 内联优化
- 无运行时类型信息
- 编译时多态
4. 安全取消 #
所有操作都支持取消:
- 传播取消信号
- 清理资源
- 防止孤立任务
2.1.3 数据流 #
用户调用 I/O 操作
↓
挂起当前协程
↓
提交到事件循环
↓
调度其他协程
↓
I/O 完成通知
↓
恢复挂起的协程
↓
返回结果给用户