Связь между несколькими отдельными модулями ядра (драйверами)

Чтобы добиться лучшей инкапсуляции и модульности, я решил разделить драйвер ядра на 2 (может быть больше) модуля, каждый из которых отвечает за разные функции.

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

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

Загвоздка в том, что каждый модуль ядра имеет свою собственную таблицу символов, и для публикации API необходим какой-то загрузчик для исправления адресации/указателей/и т. д. Это похоже на вызов dlopen и dlsym из пользовательского пространства при динамическом связывание с библиотекой, но в пространстве ядра и где каждая библиотека также имеет состояние (состояние, определяемое текущим моментальным снимком всех ее внутренних параметров кучи/глобальных).

Мой вопрос заключается в том, является ли этот подход действительным и принятым в сфере macOS?

РЕДАКТИРОВАТЬ, в следующем вопросе объясняется способ Linux для достижения моей цели , Возможно, вы знаете, что эквивалентно symbol_get и symbol_put в macOS/XNU?


person Community    schedule 11.12.2017    source источник
comment
В вашем вопросе не упоминается macOS/xnu, но упоминается FreeBSD. Что он? В последнем случае теги kernel-extension и xnu не подходят.   -  person pmdj    schedule 11.12.2017
comment
Исправлен вопрос, чтобы соответствовать тегам. Я знаю, что инфраструктура драйверов xnu сильно отличается от Linux и основана на коде C++, но я пытаюсь найти наш подход, если совместное использование API/памяти для связи с драйверами в целом является подходящим подходом. Если у вас есть какие-либо мысли/комментарии по поводу такой подход, я был бы рад услышать. Благодарность !   -  person    schedule 11.12.2017
comment
В настоящее время для ответа на ваш вопрос требуются знания как в ядре Linux, так и в ядре Mac OS. Например. Я знаю о Linux (его модули ядра могут взаимодействовать так же, как библиотеки пользовательского пространства), но не знаю о Mac OS. Вместо этого спросите об одной (конкретной) ОС.   -  person Tsyvarev    schedule 12.12.2017
comment
@tsyvarev, хорошо, я получил ваш комментарий, я просто предположил, что эта концепция универсальна и широко используется в отрасли. Я видел, что в macOS вы можете определить библиотеки без сохранения состояния и связать их с другим модулем ядра с полным состоянием. Однако я хотел взаимодействовать между двумя живыми модулями, а не просто набором функций. В любом случае, я удалил тег macOS ... возможно, вы можете поделиться своими знаниями в области Linux? Благодарность !   -  person    schedule 12.12.2017
comment
Возможный дубликат межмодульной связи в ядре Linux   -  person mrdvlpr    schedule 12.12.2017
comment
В Linux модули ядра являются модулями объектов, они могут (и делают) экспортировать и импортировать символы. Используйте modinfo и nm -g для подробностей.   -  person Lorinczy Zsigmond    schedule 12.12.2017
comment
@mrdvlpr, спасибо, что сообщили мне, что избавило меня от долгих поисков, возможно, вы знакомы с xnu? Я хочу найти способ сделать это и на этой платформе. Обратите внимание, что я соответствующим образом отредактировал свой вопрос.   -  person    schedule 12.12.2017


Ответы (1)


Похоже, Linux-стороне уже ответили в комментариях.

Для кекстов macOS следует использовать механизм OSBundleLibraries и OSBundleCompatibleVersion свойства Info.plist. Для kext экспортирующих символов должно быть установлено свойство OSBundleCompatibleVersion. Это должно быть меньше или равно его CFBundleVersion и позволяет вам управлять версиями вашего API.

Кекст, который хочет импортировать другие символы кекста, должен перечислить идентификатор пакета кекста для экспорта в словаре OSBundleLibraries с соответствующим номером версии.

Обратите внимание, что связывание с другим kext приведет к импорту всех его общедоступных символов, поэтому я настоятельно рекомендую сделать все символы скрытыми по умолчанию и предоставить явный файл экспорта. Для этого включите «Символы, скрытые по умолчанию» в настройках цели Xcode, создайте новый файл .exp (или .exports) и объявите его в настройке «Файл экспортируемых символов». Как минимум вам нужно будет добавить _kmod_info в этот файл. Затем добавьте все символы, которые вы хотите экспортировать, по одному в каждой строке.

Функции C и глобальные переменные должны иметь префикс подчеркивания, функции C++ и статические переменные-члены класса должны быть искажены обычным способом. Вы можете использовать * в качестве (частичного) подстановочного знака, что иногда удобно, например, для классов C++ с большим количеством функций-членов. Исходный дистрибутив xnu содержит множество примеров файлов экспорта, если вам нужна ссылка. Вы можете использовать инструмент nm для создания списка всех символов в вашем kext, из которого затем вы можете выбрать и выбрать; это избавит вас от ручного изменения имен.

Кексты не могут циклически зависеть друг от друга. Один должен быть «библиотекой», другой — «пользователем» этой библиотеки. Если им нужно взаимодействовать, вам нужно будет использовать обратные вызовы, виртуальные функции и т. д.

Кекст "библиотека" должен быть установлен в /Library/Extensions (/System/Library/Extensions в OS X 10.8 или более ранней версии), иначе пользователь библиотеки не найдет ее, возможно, даже если библиотечный kext уже загружен. Если ваш «пользовательский» kext указывает в своем свойстве OSBundleRequired, что он может потребоваться для загрузки по локальной или сети, библиотеки, от которых он зависит, должны объявить те же или расширенный набор этих условий, или они не могут быть должным образом предварительно связаны/kextcached.

У Apple есть небольшое количество документации по проектированию библиотеки kext тоже.

person pmdj    schedule 12.12.2017
comment
Отличный ответ, спасибо! Я начал реализовывать соответствующим образом и сообщать вам о любых проблемах, если таковые имеются. - person ; 12.12.2017
comment
Да, это работает ! еще раз спасибо ... Кстати, я думаю, это невозможно, но, возможно, вы знаете, могу ли я загрузить свой клиентский kext, даже если библиотека kext не загружена (с локальной реализацией экспортированных символов)? или, может быть, даже более экстремально... возможно, есть способ загрузить kext, который динамически решает, загружена ли его библиотека, и соответственно переключаться между локальной и удаленной реализацией. - person ; 13.12.2017
comment
У вас могут быть слабые символы, как и в любом другом двоичном файле Mach-O, но я не думаю, что у вас может отсутствовать целая зависимость kext. Я подозреваю, что kextd не загрузит ваш kext, если одна из OSBundleLibraries не может быть найдена, даже если нет неразрешенных жестких ссылок. Однако один из способов сделать это - не помечать его как зависимость, а вместо этого выполнять всю связь через классы C++ на основе OSObject. Вы можете создавать экземпляры таких классов на основе имени класса (в виде строки), и если этот класс не существует, он должен просто сообщить об ошибке. Поэтому, если библиотека kext не загружена, она должна выйти из строя. - person pmdj; 13.12.2017
comment
Это очень интересный подход, я не знал о возможности реализации createInstance, которая потерпит неудачу, если имя класса не существует во время выполнения. Но как именно загрузка нового модуля сделает класс внезапно существующим... возможно, я спрошу это в другой теме, так как это широкая тема. - person ; 13.12.2017
comment
Привет, я последовал вашей инструкции и собрал библиотеку kext, основанную на универсальном расширении ядра, которое использует класс С++ для хранения всей логики (класс, основанный на OSObject, чтобы я мог перезаписать его другим производным классом). однако, похоже, я не могу правильно освободить объект класса, возможно, вы можете задать мой вопрос здесь: https://stackoverflow.com/questions/47990273/macos-generic-kernel-extension-with-c-class спасибо - person ; 27.12.2017