1-20.【GCD】DispatchSource 是如何与内核事件(kqueue / mach)关联的?

18 阅读2分钟

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 与内核事件的绑定流程

文件可读事件 为例:

  1. 创建 DispatchSource
let source = DispatchSource.makeReadSource(fileDescriptor: fd, queue: queue)

2. 注册内核事件

  • GCD 会调用 kevent 或 Mach API,把文件描述符 fd 注册到内核事件表

  • 告诉内核:

    • “当 fd 可读时,通知我”
  1. 内核检测事件
  • 内核监控文件描述符
  • fd 可读时,内核把事件标记为 ready
  1. 事件派发到 GCD
  • 内核通知 GCD (kqueue 或 Mach port)
  • GCD 在目标队列上 异步执行事件 handler
  • 用户注册的 block 在队列上被调用

时序示意

用户空间: DispatchSource.makeReadSource -> GCD
内核空间: kqueue 注册 fd
事件触发 -> 内核通知 GCD
GCD 派发 -> 队列执行事件 handler

4️⃣ 特点与优势

特性DispatchSource + 内核事件
异步驱动✅ 内核通知,无需轮询
高性能✅ 内核直接触发事件,低开销
线程安全✅ 回调在指定 GCD 队列
支持多种事件类型✅ 文件、信号、进程、Mach 消息、定时器

内核负责事件检测,GCD 负责队列调度 → 高性能异步事件驱动模型


5️⃣ 与 NSTimer / RunLoop 的对比

特性DispatchSourceNSTimer
驱动机制内核事件 + GCD 队列RunLoop 轮询
精度中等 / 低
阻塞影响RunLoop 阻塞会延迟触发
类型多系统事件支持仅时间触发

6️⃣ 总结

DispatchSource 底层原理

  1. 用户空间创建 DispatchSource → 指定队列 + 事件类型
  2. GCD 调用内核接口注册事件(kqueue / Mach port)
  3. 内核监控事件,当事件发生 → 通知 GCD
  4. GCD 在目标队列异步执行事件 handler

核心思想:用户空间的高层事件对象 + 内核事件通知 + GCD 异步调度 → 高效、线程安全、低开销


DispatchSource 与内核事件的流程图,从“注册 → 内核监控 → GCD 派发 → 队列执行”完整展示事件流。

image.png