Сервер работает в ядре Linux. Слушать должно происходить в потоке или нет? - PullRequest
1 голос
/ 05 марта 2009

Я пишу клиент / сервер в ядре Linux (Да. Внутри ядра. Его проектное решение принято и доработано. Его не изменится)

Сервер читает входящие пакеты из необработанного сокета. Транспортный протокол для этих пакетов (на котором прослушивается необработанный сокет) является пользовательским и похож на UDP. Короче говоря, мне не нужно прослушивать входящие соединения, а затем разветвлять поток для обработки этого соединения.

Мне нужно просто обработать любую IP-дейтаграмму, поступающую на этот необработанный сокет. Я буду продолжать читать пакеты в бесконечном цикле на необработанном сокете. В эквивалентной программе пользовательского уровня я бы создал отдельный поток и продолжал прослушивать входящие пакеты.

Теперь для сервера уровня ядра у меня есть сомнения относительно того, должен ли я запускать его в отдельном потоке или нет, потому что:

  1. Я думаю, что read () - это операция ввода-вывода. Так что где-то внутри read () ядро ​​должно вызывать функцию schedule (), чтобы освободить управление процессором. Таким образом, после вызова read () в необработанном сокете текущий активный контекст ядра будет удерживаться (может быть, помещен в очередь ожидания?), Пока пакеты не станут доступны. Когда пакеты будут доставлены, контекст прерывания ядра будет сигнализировать о том, что контекст чтения, который находится в очереди, снова готов к работе. Я специально использую здесь «контекст» вместо «нить». Таким образом, я не должен требовать отдельного потока ядра.

  2. С другой стороны, если read () не оставляет управление, тогда все ядро ​​будет заблокировано.

Кто-нибудь может дать советы о том, как мне проектировать мой сервер? В чем ошибочность аргумента, представленного в пункте 1?

Ответы [ 2 ]

2 голосов
/ 06 марта 2009

Я не уверен, нужен ли вам вообще необработанный сокет в ядре. Внутри ядра вы можете добавить ловушку netfilter или зарегистрировать что-то еще (???), которое будет принимать все пакеты; это может быть то, что вы хотите.

Если вы использовали DID-сокет внутри ядра, то вам, вероятно, понадобится поток ядра (то есть запущенный kernel_thread) для вызова read (). Но это не обязательно должен быть поток ядра, это может быть поток пользовательского пространства, который только что совершил специальный системный вызов или вызов устройства для вызова нужной подпрограммы режима ядра.

Если у вас зарегистрирован хук, контекст, в котором он вызывается, вероятно, не должен выполнять слишком много обработки; Я точно не знаю, что это может быть, это может быть «обработчик нижней половины» или «тасклет», какими бы они ни были (эти типы управляющих структур постоянно меняются от одной версии к другой). Я надеюсь, что на самом деле это не процедура обработки прерываний.


В ответ на ваш оригинальный вопрос:

  1. Да, sys_read заблокирует вызывающий поток, будь то поток ядра или пользовательский. Система не будет зависать. Однако, если вызывающий поток не находится в состоянии, когда блокировка имеет смысл, ядро ​​будет паниковать (планируя прерывание или что-то в этом роде)

Да, вам нужно будет сделать это в отдельном потоке, нет, это не приведет к зависанию системы. Однако выполнение системных вызовов в режиме ядра очень сомнительно, хотя и работает (вроде).

Но если вместо этого вы установили какой-то хук, вам не нужно будет ничего этого делать.

0 голосов
/ 05 марта 2009

Я думаю, что вам лучше всего подражать тому, как пишутся драйверы, думать о вашем сервере как о виртуальном устройстве, расположенном поверх тех, от которых поступают запросы. Пример: драйвер мыши принимает непрерывный ввод, но не блокирует систему, если запрограммирован правильно, и сетевой адаптер, вероятно, больше похож на ваш случай.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...