1️⃣ 核心结论
DispatchSource 是 GCD 提供的事件源对象,它在底层使用内核机制(macOS/iOS 上是 kqueue、Mach port 等)注册系统事件,并把内核事件转化为 GCD 队列的异步回调。
换句话说:
- DispatchSource ≈ 用户空间的事件封装 + 内核事件注册
- 事件发生 → 内核通知 → GCD 派发到队列 → 回调执行
2️⃣ 内核事件机制概览
2.1 kqueue(文件 / I/O /信号)
-
kqueue 是 BSD / macOS / iOS 的事件通知机制
-
特点:
- 用户空间注册感兴趣事件(文件可读/可写、信号、进程状态等)
- 内核在事件发生时通知用户空间(无需轮询)
-
DispatchSourceFileSystemObject / READ / WRITE / SIGNAL 类型背后就是 kqueue
2.2 Mach port(Mach 消息 / 定时器)
- macOS/iOS 内核使用 Mach 内核端口管理消息和通知
- DispatchSourceTimer / MACH_RECV / MACH_SEND 通过 Mach port 接收内核事件
3️⃣ DispatchSource 与内核事件的绑定流程
以 文件可读事件 为例:
- 创建 DispatchSource
let source = DispatchSource.makeReadSource(fileDescriptor: fd, queue: queue)
2. 注册内核事件
-
GCD 会调用
kevent或 Mach API,把文件描述符 fd 注册到内核事件表 -
告诉内核:
- “当 fd 可读时,通知我”
- 内核检测事件
- 内核监控文件描述符
- fd 可读时,内核把事件标记为 ready
- 事件派发到 GCD
- 内核通知 GCD (kqueue 或 Mach port)
- GCD 在目标队列上 异步执行事件 handler
- 用户注册的 block 在队列上被调用
时序示意
用户空间: DispatchSource.makeReadSource -> GCD
内核空间: kqueue 注册 fd
事件触发 -> 内核通知 GCD
GCD 派发 -> 队列执行事件 handler
4️⃣ 特点与优势
| 特性 | DispatchSource + 内核事件 |
|---|---|
| 异步驱动 | ✅ 内核通知,无需轮询 |
| 高性能 | ✅ 内核直接触发事件,低开销 |
| 线程安全 | ✅ 回调在指定 GCD 队列 |
| 支持多种事件类型 | ✅ 文件、信号、进程、Mach 消息、定时器 |
内核负责事件检测,GCD 负责队列调度 → 高性能异步事件驱动模型
5️⃣ 与 NSTimer / RunLoop 的对比
| 特性 | DispatchSource | NSTimer |
|---|---|---|
| 驱动机制 | 内核事件 + GCD 队列 | RunLoop 轮询 |
| 精度 | 高 | 中等 / 低 |
| 阻塞影响 | 无 | RunLoop 阻塞会延迟触发 |
| 类型 | 多系统事件支持 | 仅时间触发 |
6️⃣ 总结
DispatchSource 底层原理:
- 用户空间创建 DispatchSource → 指定队列 + 事件类型
- GCD 调用内核接口注册事件(kqueue / Mach port)
- 内核监控事件,当事件发生 → 通知 GCD
- GCD 在目标队列异步执行事件 handler
核心思想:用户空间的高层事件对象 + 内核事件通知 + GCD 异步调度 → 高效、线程安全、低开销
DispatchSource 与内核事件的流程图,从“注册 → 内核监控 → GCD 派发 → 队列执行”完整展示事件流。