Проблема в том, что вы пытаетесь вставить приложение пространства пользователя в ядро .
Сокеты (и файлы и т. Д.) - это то, что ядро предоставляет приложениям пользовательского пространства через ядро-пользовательское пространство API / ABI . Некоторые , но не все, также могут вызываться в ядре, если другое ядро хочет использовать что-то, предоставленное для пространства пользователя.
Давайте посмотрим на реализацию ядра Linux.системных вызовов socket()
или accept()
в net / socket.c в исходных кодах ядра;ищите SYSCALL_DEFINE3(socket,
и SYSCALL_DEFINE3(accept,
, SYSCALL_DEFINE4(recv,
и т. д.
(я рекомендую использовать, например, Elixir Cross Referencer , чтобы найти конкретные идентификаторы в исходных кодах ядра Linux, затемищите реальный код в одном из официальных Git-деревьев ядра в сети; в любом случае, это то, что я делаю.)
Обратите внимание, что аргументы указателя имеют квалификатор __user
: это означает, что данные, на которые указывают, должны находиться в пользовательское пространство , и что функции в конечном итоге будут использовать copy_from_user()
/ copy_to_user()
для извлечения или установки данных.Кроме того, операции обращаются к таблице дескрипторов файлов , которая является частью контекста процесса : то, что обычно существует только для процессов пользовательского пространства.
По сути, это означает, что выМодуль ядра должен создать «процесс» пользовательского пространства (достаточно одного, чтобы удовлетворить требования пересечения границы пользовательского пространства-ядра при использовании интерфейсов ядра), чтобы как минимум «удерживать» дескрипторы памяти и файлов.Это большая работа, и, в конце концов, она не будет более производительной, чем приложение в пользовательском пространстве.(Разработчики ядра Linux работали над этим буквально десятилетия. Есть некоторые проприетарные операционные системы, в которых работа в «пространстве ядра» может быть быстрее, но в Linux это не так. Стоимость работы в пользовательском пространстве - это переключение контекста,и, возможно, некоторые копии памяти (для передаваемых данных).)
В частности, интерфейсы TCP / IP и UDP / IP (см., например, net / ipv4 / udp.c для UDP /IPv4), похоже, не имеет никакого интерфейса для буферов на стороне ядра (кроме прямого доступа к буферам сокетов rx / tx, которые находятся в памяти ядра).
Возможно, вы слышали о Веб-сервер TUX , подсистема , исправление для ядра Linux от Ingo Molnár.Даже это не «сервер модуля ядра», а скорее подсистема, которую процесс пользовательского пространства может использовать для реализации сервера, который в основном работает в пространстве ядра.
Идея модуля ядра, обеспечивающего TCP /IP и / или сервер UDP / IP, это все равно что пытаться использовать молоток для ввинчивания винтов.Он будет работать по-своему, но результаты не будут хорошими.
Тем не менее, для конкретного случая эхо-сервера, возможно, можно просто подключить его к IPv4 (см. * 1057).* net / ipv4 / ) и / или IPv6 (см. net / ipv6 / ) аналогично пакетам ICMP ( net / ipv4 / icmp.c , net /ipv6 / icmp.c ).Я бы рассмотрел этот путь тогда и только тогда, когда вы намереваетесь специализироваться на сетевых вещах на стороне ядра, так как в противном случае все, что вы изучите, делает это очень специализированным и не очень полезным на практике.
Если выМне нужно реализовать что-то на стороне ядра для упражнения или чего-то такого, я бы порекомендовал отказаться от идей типа «приложения» (сервисы или аналогичные).
Вместо этого я бы настоятельно рекомендовал разработать драйвер символьного устройства,возможно, реализует некоторый уровень межпроцессного взаимодействия, предпочтительно в стиле шины (то есть один отправитель, любое количество получателей).Нечто подобное имеет ряд реальных реальных вариантов использования (как аппаратных драйверов, так и странных вещей, таких как вещи типа kdbus), так что все, что вы изучите, будет практичным.
(На самом деле символьное устройство эха, которое просто выводит все, что ему записано, является отличной первой целью. Хотя LDD3 предназначено для ядра Linux 2.6.10, оно должно быть отличным чтениемдля тех, кто занимается разработкой ядра Linux. Если вы используете более новое ядро, просто помните, что пример кода может не скомпилироваться как есть, и вам, возможно, придется провести некоторые исследования в отношении репозитория Git ядра Git и / или кросс-кода ядрасправочник, как эликсир выше.)