3

我有一个线程在单个 UDP 套接字上侦听,但也需要不时唤醒以执行其他任务。这些任务由时间流逝或其他线程上的活动触发。我目前的设计是使用 select() 超时值作为调度计时器,并在我需要从另一个线程唤醒它时将数据包写入套接字(环回)地址。

但是,Apple 文档说 select() 超时不应用于每秒唤醒超过几次。而且,在实践中,我发现它们可能会延迟 100 毫秒或更多,而我想要 10-20 毫秒的分辨率。他们只是想阻止 cpu 密集型轮询,还是使用 select() 本身有问题。有更好的方法吗?

用 kqueue/kevent 替换 select 会有帮助吗?或者,创建一个专门的调度线程,用mach_wait_until()来处理定时器,然后写入socket来唤醒net线程?或者,在专用线程中完成所有工作,并让网络线程将传入数据排队?

4

1 回答 1

0

这种方法让我有些不快。为什么你在 select() 线程上发生了什么事?

如果您需要一个专门用于等待传入数据包的线程,它们会尽可能地使该线程等待。

while (1) {
    int numsockets = select(…);
    if (numsockets > 0) {
        // Read data (only drain the socket)
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            // Process data
        });
    }
}

然后,您可以使用timer dispatch sources让您的周期性任务运行。

dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,
                                                  dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));

dispatch_source_set_event_handler(source, ^{
    // Periodic process data
});

uint64_t nsec = 0.001 * NSEC_PER_SEC;
dispatch_source_set_timer(source, dispatch_time(DISPATCH_TIME_NOW, nsec), nsec, 0);
dispatch_resume(source);

我不知道,但有人告诉我,您甚至可以使用调度源来替换 select()。

于 2013-10-02T02:19:08.800 回答