代码之家  ›  专栏  ›  技术社区  ›  Methos

在Linux内核中运行的服务器。是否应该在线程中进行侦听?

  •  1
  • Methos  · 技术社区  · 16 年前

    我正在用Linux内核编写客户机/服务器(是的。在内核内部。它的设计决定已作出并最终确定。不会改变的)

    服务器从原始套接字读取传入数据包。这些数据包的传输协议(原始套接字正在侦听)是自定义的,类似于UDP。简而言之,我不需要监听传入的连接,然后分叉一个线程来处理该连接。

    我只需要处理来自原始套接字的任何IP数据报。我将继续在原始套接字上无限循环读取数据包。在用户级的等效程序中,我会创建一个单独的线程,并不断地监听传入的数据包。

    现在对于内核级服务器,我怀疑是否应该在单独的线程中运行它,因为:

    1. 我认为read()是一个I/O操作。所以在read()中的某个地方,内核必须调用schedule()函数来放弃对处理器的控制。因此,在原始套接字上调用read()之后,当前的内核活动上下文将被挂起(是否放入睡眠队列?)直到数据包可用。当数据包到达时,内核中断上下文将发出信号,表示正在队列中休眠的读取上下文再次准备好运行。我在这里故意使用“context”,而不是“thread”。因此,我不需要单独的内核线程。

    2. 另一方面,如果read()不放弃控件,那么整个内核将被阻塞。

    有人能提供我应该如何设计服务器的提示吗? 第1点中提出的论点的谬误是什么?

    2 回复  |  直到 16 年前
        1
  •  2
  •   MarkR    16 年前

    我不确定您是否需要内核中的原始套接字。在内核中,您可以添加一个netfilter钩子,或者注册其他东西(???)它将接收所有数据包;这可能是您想要的。

    如果在内核中使用了原始套接字,那么可能需要有一个内核线程(即由内核线程启动)来调用read()。但是它不需要是内核线程,它可以是一个用户空间线程,它只是进行了一个特殊的系统调用或设备调用来调用所需的内核模式例程。

    如果您注册了一个钩子,它调用的上下文可能是一些不应该做太多处理的内容;我不知道可能是什么,它可能是“下半部分处理程序”或“tasklet”,不管是什么(这些类型的控制结构不断从一个版本变为另一个版本)。我希望这不是一个真正的中断服务程序。


    回答你原来的问题:

    1. 是的,无论是内核线程还是用户空间线程,sys-read都会阻止调用线程。系统不会挂起。但是,如果调用线程不处于阻塞有意义的状态,那么内核将死机(以中断或其他方式调度)

    是的,您需要在单独的线程中执行此操作,不,它不会挂起系统。然而,在内核模式下进行系统调用是非常困难的,尽管它确实可以工作(有点)。

    但是如果你安装了某种钩子,你就不需要这样做了。

        2
  •  0
  •   Dana the Sane    16 年前

    我认为您最好的选择可能是模仿驱动程序的编写方式,将您的服务器视为一个虚拟设备,位于请求所来自的设备之上。示例:鼠标驱动程序接受连续输入,但如果编程正确,则不会锁定系统,网络适配器可能更类似于您的情况。