Обзор расширения ядра

Как обсуждено в Обзоре архитектуры Ядра главы, OS X обеспечивает механизм расширения ядра как средние значения разрешения динамической загрузки кода в ядро без потребности перекомпилировать или повторно соединиться. Поскольку эти расширения ядра (KEXTs) обеспечивают и модульный принцип и динамический loadability, они - естественный выбор для любой относительно автономной службы, требующей доступа к внутренним интерфейсам ядра.

Поскольку KEXTs работают в привилегированном режиме в адресном пространстве ядра, их также более трудно записать и отладить, чем модули пользовательского уровня, и должны соответствовать строгим инструкциям. Далее, ресурсы ядра соединены проводом (постоянно резидентный объект в памяти) и таким образом более дорогостоящие для использования, чем ресурсы в задаче пространства пользователя эквивалентной функциональности.

Кроме того, несмотря на то, что защита памяти препятствует приложениям разрушать систему, никакие такие гарантии не существуют в ядре. Плохо себя ведомое расширение ядра в OS X может доставить столько же неприятностей сколько плохо себя ведомое приложение, или расширение могло в Mac OS 9.

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

Наконец, для соображений безопасности, некоторые клиенты ограничивают или не разрешают использование стороннего KEXTs. В результате использованию KEXTs строго обескураживают в ситуациях, где решения пользовательского уровня выполнимы. OS X гарантирует, что поточная обработка в приложениях так же эффективна как распараллеливающий в ядре, таким образом, эффективность не должна быть проблемой. Если Ваше приложение не требует низкоуровневого доступа к интерфейсам ядра, необходимо использовать более высокий уровень абстракции при разработке кода для OS X.

Когда Вы пытаетесь определить, должна ли часть кода быть KEXT, ответ по умолчанию обычно нет. Даже если Ваш код был системным расширением в Mac OS 9, который не обязательно означает, что это должно быть расширение ядра в OS X. Существует только несколько серьезных оснований для разработчика записать расширение ядра:

Если Ваш код не удовлетворяет ни одного из вышеупомянутых критериев (и возможно даже если он делает), необходимо рассмотреть разработку его как библиотеку или демона пользовательского уровня или использование одной из архитектуры плагина пользовательского уровня (такой как компоненты QuickTime или Базовая Графическая платформа) вместо того, чтобы писать расширение ядра.

Если Вы пишете драйверы устройств или код для поддержки нового формата объема или сетевого протокола, однако, KEXTs может быть единственным выполнимым решением. К счастью, в то время как KEXTs может быть более трудно записать, чем код пространства пользователя, несколько инструментов и процедур доступны для улучшения процесса разработки и процесса отладки. Посмотрите Отладку Вашего KEXT для получения дополнительной информации.

Эта глава обеспечивает концептуальный обзор KEXTs и как создать их. Если Вы интересуетесь созданием простого KEXT, см. учебные руководства Apple, перечисленные в библиографии. Они обеспечивают поэтапные инструкции для создания простого, универсального KEXT или основного драйвера Набора I/O.

Реализация расширения ядра (KEXT)

Расширения ядра реализованы как пакеты, папки, которые Средство поиска обрабатывает как единственные файлы. См. главу о пакетах в Технологическом Обзоре Mac для обсуждения пакетов. Пакет KEXT может содержать следующее:

Зависимости от расширения ядра

Любой KEXT может объявить, что это зависит от любого другого KEXT. Разработчик перечисляет эти зависимости в OSBundleLibraries словарь в файле списка свойств модуля.

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

Например, драйверы устройств (тип KEXT) зависят от (требуют) определенных семей (другой тип KEXT). Когда драйвер загружается, его требуемые семьи также загружаются для обеспечения необходимой, общей функциональности. Чтобы гарантировать, что все требования удовлетворяются, каждый драйвер устройства должен перечислить все свои требования (семьи и другие драйверы) в его списке свойств. См. главу Обзор Набора I/O для объяснения драйверов и семей.

Важно перечислить все зависимости для каждого KEXT. Если Ваш KEXT перестал работать для этого, Ваш KEXT может не загрузиться вследствие нераспознанных символов, таким образом представив бесполезное KEXT. Зависимости в KEXTs можно считать аналогичными требуемым заголовочным файлам или библиотекам в разработке кода; фактически, менеджер по Расширению ядра использует типичного компоновщика для разрешения требований KEXT.

Создание и тестирование расширения

После создания списка необходимого свойства и C или исходных файлов C++, Вы используете Разработчика Проекта для создания KEXT. Любым ошибкам в исходном коде представляют Вашему вниманию во время сборки, и Вам дают шанс отредактировать Ваши исходные файлы и попробовать еще раз.

Для тестирования KEXT, однако, необходимо оставить Разработчика Проекта и работать в Терминальном приложении (или в консольном режиме). В консольном режиме все системные сообщения записаны непосредственно в Ваш экран, а также в файл журнала (/var/log/system.log). Если Вы работаете в Терминальном приложении, необходимо просмотреть системные сообщения в файле журнала или в Консольном приложении. Также необходимо войти в корневой аккаунт (или использовать su или sudo команда), так как только корневая учетная запись может загрузить расширения ядра.

При тестировании KEXT можно загрузить и разгрузить его вручную, а также проверить состояние загрузки. Можно использовать kextload команда для загрузки любого KEXT. Страница руководства для kextload включен в OS X. (На OS X до 10,2, необходимо использовать kmodload команда вместо этого.)

Обратите внимание на то, что эта команда полезна только при разработке KEXT. В конечном счете, после того, как это было протестировано и отлажено, Вы устанавливаете свой KEXT в одном из стандартных мест (см. Установленный KEXTs для подробных данных). Затем это будет загружено и разгружено автоматически при системном запуске и завершении работы или каждый раз, когда это необходимо (такой как тогда, когда новое устройство обнаруживается).

Отладка Вашего KEXT

Отладка KEXT может быть сложной. Прежде чем можно будет отладить KEXT, необходимо сначала включить отладку ядра, поскольку OS X обычно не конфигурируется, чтобы разрешить отлаживать ядро. Только корневая учетная запись может включить отладку ядра, и необходимо перезагрузить OS X для изменений для вступления в силу. (Можно использовать sudo получать полномочия пользователя root, если Вы не хотите включать пароль root.)

Отладка ядра выполняется с помощью двух компьютеров OS X, названных узлом разработки или отладки и целевым объектом отладки. Эти компьютеры должны быть подключены по надежному сетевому соединению на той же подсети (или в единой локальной сети). В частности не должно быть никаких прошедших маршрутизаторов IP или других устройств, которые могли сделать основанный на аппаратных средствах Ethernet, адресующийся невозможный.

KEXT регистрируется (и загружается и выполняется) на цели. Отладчик запускается и работается узел отладки. Можно также восстановить KEXT на узле отладки после фиксации любых ошибок, которые Вы находите.

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

Обратите внимание на то, что ошибки в KEXTs могут заставить целевое ядро замораживаться или паниковать. Если это происходит, Вы не можете быть в состоянии продолжать отлаживать, даже по удаленному соединению; необходимо перезагрузить цель и запуститься, установив точку останова как раз перед кодом, где KEXT отказал и работающий очень тщательно до точки катастрофического отказа.

Разработчики обычно отлаживают KEXTs, использующий gdb, отладчик исходного уровня с интерфейсом командной строки. Необходимо будет работать в Терминальном приложении для выполнения gdb. Для получения дальнейшей информации об использовании gdb, см. документацию, включенную с OS X. Можно также использовать help команда из gdb.

Некоторые функции gdb недоступны при отладке KEXTs из-за ограничений реализации. Например:

Прежний - в основном барьер, представленный языком C++. Последний может работать в некоторых случаях, но не рекомендуется вследствие потенциала для gdb прерывать теми, что-то на который kdp (контейнер ядра, используемый gdb) зависит для функционирования должным образом.

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

Дополнительная информация об отладке может быть найдена в том, Когда Вещи Идут не так, как надо: Отладка Ядра.

Установленный KEXTs

Менеджер по Расширению ядра (менеджер по KEXT) ответственен за загрузку и разгрузку, все установили KEXTs (команды такой как kextload используются только во время разработки). Установленные KEXTs динамично добавляются к рабочему ядру OS X как часть адресного пространства ядра. Установленный и включил KEXT, вызывается по мере необходимости.

KEXTs обычно устанавливаются в папке /System/Libraries/Extensions. Менеджер по Расширению ядра (в форме демона, kextd), всегда проверки здесь. KEXTs может также быть установлен в ROM или в комплекте приложений.

Установка KEXTs в комплекте приложений позволяет приложению регистрировать те KEXTs без потребности установить их постоянно в другом месте в системной иерархии. Это может быть более удобным и позволяет KEXT быть связанным с определенным, запущенным приложением. Когда это запускается, приложение может зарегистрировать KEXT и при желании не зарегистрировать его на выходе.

Например, приложение сниффера сетевого пакета могло бы нанять Network Kernel Extension (NKE). Приложение резервного копирования на магнитную ленту потребовало бы, чтобы драйвер ленты был загружен во время продолжительности процесса резервного копирования. Когда приложение выходит, расширение ядра больше не необходимо и может быть разгружено.

Обратите внимание на то, что, несмотря на то, что приложение ответственно за регистрацию KEXT, это не гарантия, что фактически когда-либо загружаются соответствующие KEXTs. Это все еще до компонента ядра, такого как Набор I/O, для определения потребности, такой как соответствие части аппаратных средств к желаемому драйверу, таким образом заставляя надлежащий KEXTs (и их зависимости) быть загруженным.