GCD中Workloop、Kevent机制探究

最新iOS系统特性开启情况分析

Xcode中增加对pthread_workqueue_setup函数的symbolic_breakpoint

GCD的注册点位入口:

int
_pthread_workqueue_init_with_workloop(pthread_workqueue_function2_t queue_func,
        pthread_workqueue_function_kevent_t kevent_func,
        pthread_workqueue_function_workloop_t workloop_func,
        int offset, int flags)
{
    struct pthread_workqueue_config cfg = {
        .version = PTHREAD_WORKQUEUE_CONFIG_VERSION,
        .flags = 0,
        .workq_cb = queue_func,
        .kevent_cb = kevent_func,
        .workloop_cb = workloop_func,
        .queue_serialno_offs = offset,
        .queue_label_offs = 0,
    };

    return pthread_workqueue_setup(&cfg, sizeof(cfg));
}

libpthread的注册点位:

__API_AVAILABLE(macos(10.15), ios(13.0))
int
pthread_workqueue_setup(struct pthread_workqueue_config *cfg, size_t cfg_size);

struct pthread_workqueue_config {
    uint32_t flags;
    uint32_t version;
    pthread_workqueue_function_kevent_t kevent_cb;
    pthread_workqueue_function_workloop_t workloop_cb;
    pthread_workqueue_function2_t workq_cb;
    uint64_t queue_serialno_offs;
    uint64_t queue_label_offs;
};

查看$0的内存布局,读取内容,可以看到config中的三个函数指针都是有明确地址的,因此最新版本的GCD同时开启了kevent、workloop和queue功能的回调

(lldb) memory read --count 64 $x0
0x16f9e6d20: 00 00 00 00 02 00 00 00 30 89 fb 00 01 00 00 00  ........0.......
0x16f9e6d30: 6c 8c fb 00 01 00 00 00 0c 88 fb 00 01 00 00 00  l...............
0x16f9e6d40: 40 00 00 00 00 00 00 00 48 00 00 00 00 00 00 00  @.......H.......
0x16f9e6d50: 00 00 00 00 00 00 00 00 98 1b 01 01 01 00 00 00  ................

解析:
flags: 0 (无特殊标志)
version: 2 (使用版本2)
kevent_cb: 函数指针 0x1fb8930
workloop_cb: 函数指针 0x1fb8c6c
workq_cb: 函数指针 0x1fb880c
queue_serialno_offs: 64字节偏移
queue_label_offs: 72字节偏移

timer路径:

结论:timer走kevent路径

void timer()
{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

    dispatch_source_set_timer(timer,
                              dispatch_time(DISPATCH_TIME_NOW, 0),
                              1ull * NSEC_PER_SEC,
                              0);

    dispatch_source_set_event_handler(timer, ^{
        NSLog(@"tick %@", [NSDate date]);
    });

    dispatch_resume(timer);

    // 阻塞主线程,运行 GCD 主循环
    dispatch_main();
}
Screenshot 2025-09-28 at 17.48.48.png

Screenshot 2025-09-28 at 17.53.43.png

workloop路径:

void workloop()
{
    dispatch_workloop_t wl = dispatch_workloop_create("com.example.workloop");
    
    dispatch_async(wl, ^{
        NSLog(@"任务 A");
    });
    
    exit(0);
}
Screenshot 2025-09-29 at 10.07.46.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容