我最近对内核事件进行了一些测试,并提出了以下内容:

  • 使用内核事件接受套接字是否有意义?我的测试表明,我只能一次处理一个接受(即使事件列表数组更大)(对我来说,.ident == sockfd仅对一个套接字有效)。
  • 我认为kevent的用途主要是一次从多个套接字读取。真的吗?

  • 这是用kqueue实现完成TCP服务器的方式吗? :

  • 监听线程(无kqueue)
  • 接受新的连接,并将FD添加到工作队列中。
    问题:甚至可能吗?我的测试显示是,但是是否可以保证工作线程将知道更改,并且kevent确实是线程安全的吗?


  • worker 线程(带有kqueue)
  • 等待读取从监听线程添加的文件描述符。

  • 问题:一次检查更新是否有意义?

    谢谢

    最佳答案

    通常,您可以使用kqueue替代线程。如果要使用线程,则可以只为每个接受的连接设置一个监听线程和一个工作线程池。那是一个简单得多的编程模型。

    在事件驱动的框架中,您可以将监听套接字和所有接受的套接字都放入kqueue中,然后在事件发生时对其进行处理。接受套接字后,将其添加到队列中,当套接字处理程序完成工作时,可以从队列中删除该套接字。 (通常不需要后者,因为关闭fd会自动从任何队列中删除所有关联的事件。)

    请注意,向kqueue注册的每个事件都有一个void*用户数据,该数据可用于在事件触发时识别所需的操作。因此,不必每个事件队列都具有唯一的事件处理程序。实际上,通常有各种各样的处理程序。 (例如,您可能还想处理通过命名管道设置的控制 channel 。)

    混合事件/线程模型当然是可能的。否则,您将无法利用多核CPU。一种可能的策略是在生产者-消费者模型中将事件队列用作调度程序。队列处理程序将直接处理监听套接字上的事件,接受连接并将接受的fd添加到事件队列中。当发生客户端连接事件时,该事件将被发布到工作队列中以供以后处理。还可能有多个工作队列,每个线程一个,让接收者猜测应该根据该线程的当前负载在哪个工作队列中放置新的连接。

    09-25 16:59