Создание универсального расширения ядра с XCode

В этом учебном руководстве Вы изучаете, как создать универсальное расширение ядра (kext) для OS X. Вы создаете простой kext, распечатывающий сообщения когда загрузка и разгрузка. Это учебное руководство не касается процесса для загрузки, или отладка Вашего kext — видят Отладку Расширения ядра с GDB после завершения этого учебного руководства для получения информации о загрузке и отладке.

Если Вы незнакомы с XCode, сначала считайте XCode Быстрый Гид.

План действий

Это эти четыре существенных шага, которые Вы выполняете:

  1. Создайте новый проект

  2. Реализуйте функции запуска и остановки

  3. Добавьте объявления библиотеки

  4. Подготовьте расширение ядра к загрузке

Это учебное руководство предполагает, что Вы зарегистрированы как администратор Вашей машины, которая необходима для использования sudo команда.

Создайте новый проект

Создание kext проекта в XCode так же просто как выбор надлежащего шаблона проекта и обеспечение имени.

  1. Запуск XCode.

  2. Выберите File> New> New Project. Панель New Project появляется.

  3. В панели New Project выберите System Plug-in из списка категорий проектов слева. Выберите Generic Kernel Extension из списка шаблонов справа. Нажать Далее.

  4. На экране, появляющемся, войти MyKext для названия продукта введите идентификатор компании и нажмите Далее.

  5. Выберите расположение для проекта и нажмите Create.

    XCode создает новый проект и выводит на экран его окно проекта. Необходимо видеть что-то вроде этого:

    ../art/Build_Active_Architecture_Only.jpg

    Новый проект содержит несколько файлов, включая исходный файл, MyKext.c, это содержит шаблоны для запуска kext и функций остановки.

  6. Удостоверьтесь, что kext создает для корректной архитектуры.

    (Если Вы не видите экран выше, выберите MyKext под Целями. Выберите вкладку Build Settings. Щелкните по треугольнику раскрытия, следующему за Архитектурой.)

    Затем для Создания Активной Архитектуры Только удостоверяются, что выбрали No — это особенно важно при выполнении 32-разрядного ядра на 64-разрядной машине.

Реализуйте функции запуска и остановки

Теперь, когда Вы создали проект, пора заставить Ваш kext сделать что-то, когда это загружается и разгрузилось. Вы сделаете так путем добавления кода к запуску kext и остановите функции, вызванные, когда kext загружен и разгружен.

Реализуйте функции запуска и остановки

  1. Открытый MyKext.c отредактировать функции остановки и запуск.

    Рисунок 1 показывает неотредактированный файл.

    Рисунок 1  , Просматривающий исходный код в XCode

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

  2. Редактирование MyKext.c соответствовать код в Перечислении 1.



    Перечисление 1  MyKext.c содержание файла

    #include <sys/systm.h>
    #include <mach/mach_types.h>
     
    kern_return_t MyKext_start (kmod_info_t * ki, void * d)
    {
        printf("MyKext has started.\n");
        return KERN_SUCCESS;
    }
     
    kern_return_t MyKext_stop (kmod_info_t * ki, void * d)
    {
        printf("MyKext has stopped.\n");
        return KERN_SUCCESS;
    }

    Заметьте это MyKext.c включает два заголовочных файла, <sys/systm.h> и <mach/mach_types.h>. Оба заголовочных файла находятся в Kernel.framework. Когда Вы разрабатываете свой собственный kext, убедиться включать только заголовочные файлы от Kernel.framework (в дополнение к любым заголовочным файлам Вы создаете), потому что только эти файлы имеют значение в среде ядра. Если Вы включаете заголовки извне Kernel.framework, Ваше расширение ядра могло бы скомпилировать, но оно, вероятно, не загрузится или работать, потому что функции и обслуживают те заголовки, определяют, не доступны в ядре.

  3. Сохраните свои изменения путем выбора File> Save.

Отредактируйте информационный список свойств

Как все пакеты, kext содержит информационный список свойств, описывающий kext. Значение по умолчанию Info.plist файл, создаваемый XCode, содержит шаблонные значения, которые необходимо отредактировать для описания kext.

kext’s Info.plist файл находится в формате XML. Каждый раз, когда возможно, необходимо просмотреть и отредактировать файл из XCode или в Редакторе Списка свойств приложение. Таким образом Вы помогаете гарантировать, чтобы Вы не добавляли элементы (такие как комментарии), который не может быть проанализирован ядром во время ранней начальной загрузки.

  1. Нажмите Info.plist в окне проекта XCode.

    XCode выводит на экран Info.plist файл в области редактора. Необходимо видеть элементы файла списка свойств, как показано на рисунке 2.

    Рисунок 2  MyKext Info.plist

    По умолчанию редактор списка свойств XCode маскирует фактические ключи и значения списка свойств. Видеть фактические ключи и значения, Щелчок управления где угодно в редакторе списка свойств и выбрать Show Raw Keys/Values из контекстного меню.

  2. Измените значение CFBundleIdentifier свойство для использования уникального префикса пространства имен.

    На строке для CFBundleIdentifier, дважды щелкните в Столбце значений для редактирования его. Выбрать com.yourcompany и измените его на com.MyCompany (или домен DNS Вашей компании наоборот). Значение должно теперь быть com.MyCompany.kext.${PRODUCT_NAME:rfc1034identifier}.

    Пакеты в OS X обычно используют соглашение о присвоении имен обратного DNS избежать конфликтов пространства имен. Это особенно важно для kexts, потому что все загрузили долю kexts единое пространство имен для идентификаторов пакета.

    Последняя часть идентификатора пакета по умолчанию, ${PRODUCT_NAME:rfc1034identifier}, когда Вы разрабатываете свой проект, заменяется установкой сборки Названия продукта для цели kext.

  3. Сохраните свои изменения путем выбора File> Save.

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

Теперь Вы готовы сконфигурировать свои настройки сборки и создать Ваш kext для проверки компиляций исходного кода. Во-первых, сконфигурируйте свои настройки сборки, чтобы создать kext для каждой архитектуры, удостовериться, что Ваш kext загрузится независимо от архитектуры ядра.

  1. Щелкните по треугольнику раскрытия, следующему за Целями в области Groups и Files.

  2. Выберите цель MyKext.

  3. Выберите File>, окно «MyKext» Info Get Info The Target открывается.

  4. В списке настроек сочтите Сборку Активной Архитектурой Только и удостоверьтесь, что неконтролируем флажок.

  5. Закройте окно Target MyKext Info.

Теперь, когда Ваш kext создает против каждой архитектуры, выберите Build> Build для разрабатывания проекта. Если сборка перестала работать, исправьте все обозначенные ошибки и восстановите перед продолжением.

Добавьте объявления библиотеки

Поскольку kexts соединяются во время загрузки, kext должен перечислить свои библиотеки в его информационном списке свойств с OSBundleLibraries свойство. На этом этапе создания Вашего kext необходимо узнать, каковы те библиотеки. Лучший способ сделать так состоит в том, чтобы работать kextlibs инструмент на Вашем созданном kext и копии его вывод в Ваш kext’s Info.plist файл.

Выполненный kextlibs на Расширении ядра

kextlibs программа командной строки, которую Вы выполняете с Терминальным приложением. Его цель состоит в том, чтобы идентифицировать библиотеки, против которых должен соединиться Ваш kext.

  1. Запустите Терминальное приложение, расположенное в /Applications/Utilities.

  2. В Окне терминала переместитесь в каталог, содержащий Ваш kext.

    XCode хранит Ваш kext в Debug папка build папка Вашего проекта (если Вы не выбрали различную конфигурацию сборки или установили различное расположение для продуктов сборки с помощью Предпочтительного диалогового окна XCode).

    $ cd MyKext/build/Debug

    Этот каталог содержит Ваш kext. Это должно иметь имя MyKext.kext. Это имя формируется из Названия продукта, как установлено в настройках сборки Вашей цели и суффиксе, в этом случае .kext.

  3. Выполненный kextlibs на Вашем расширении ядра с -xml флаг командной строки.

    Эта команда ищет все неразрешенные символы в исполнимой программе Вашего расширения ядра среди установленных расширений библиотеки (в /System/Library/Extensions/) и распечатывает фрагмент XML, подходящий для вставки в Info.plist файл. Например:

    $ kextlibs -xml MyKext.kext
            <key>OSBundleLibraries</key>
            <dict>
                    <key>com.apple.kpi.libkern</key>
                    <string>10.2</string>
            </dict>
  4. Удостовериться kextlibs вышедший с успешным состоянием путем проверки переменной оболочки $?.

    $ echo $?
    0

    Если kextlibs печать любые ошибки или выходы с ненулевым состоянием, это, возможно, было неспособно определить местоположение некоторых символов. Для этого учебного руководства известны библиотеки, но в общем использовании необходимо использовать kextfind инструмент для нахождения библиотек для любых символов этим kextlibs не может расположиться. Посмотрите Определяют местоположение Kexts для получения информации о kextfind.

  5. Выберите вывод XML kextlibs и выберите Edit> Copy.

Добавьте объявления библиотеки к информационному списку свойств

Ранее, Вы отредактировали информационный список свойств с графическим редактором списка свойств XCode. Для этой работы, однако, необходимо отредактировать информационный список свойств как текст.

  1. Щелчок управления Info.plist в окне проекта XCode, затем выберите Open As> Source Code File из контекстного меню.

    XCode выводит на экран файл Info.plist в области редактора. Необходимо видеть содержания XML файла списка свойств, как показано на рисунке 3. Обратите внимание на то, что ключи словаря и значения перечислены последовательно.

    Рисунок 3  MyKext Info.plist как текст
  2. Выберите все строки, определяющие пустой словарь OSBundleLibraries:

            <key>OSBundleLibraries</key>
            <dict/>
  3. Текст вставки в информационный словарь.

    • Если kextlibs работал успешно, выберите Edit> Paste для вставки текста, который Вы скопировали с Терминала.

    • Если kextlibs не работал успешно, вводят или вставляют этот текст в информационный словарь:

              <key>OSBundleLibraries</key>
              <dict>
                      <key>com.apple.kpi.libkern</key>
                      <string>10.0</string>
              </dict>
  4. Сохраните свои изменения путем выбора File> Save.

  5. Выберите Build> Build заключительное время для восстановления kext с новым информационным списком свойств.

Подготовьте расширение ядра к загрузке

Теперь Вы готовы подготовить свой kext к загрузке. Вы делаете это с kextutil инструмент, который может исследовать kext и определить, в состоянии ли он быть загруженным. kextutil может также загрузить kext в целях разработки, но та функциональность не охвачена в этом учебном руководстве.

Установите полномочия расширения ядра

Kexts имеют строгие требования полномочий (см., что Расширения ядра Имеют Строгие Требования к защите для подробных данных). Самый простой способ установить эти полномочия состоит в том, чтобы создать копию Вашего kext как root пользователь. Введите следующее в Терминал из надлежащего каталога и обеспечьте Ваш пароль, когда запрошено:

$ sudo cp -R MyKext.kext /tmp

Теперь, когда полномочия временной копии kext корректны, Вы готовы работать kextutil.

Выполненный kextutil

Введите следующее в Терминал:

$ kextutil -n -print-diagnostics /tmp/MyKext.kext

-n (или -no-load) опция говорит kextutil не загрузить драйвер, и -t (или -print-diagnostics) опция говорит kextutil распечатать результаты его анализа к Терминалу. Если Вы выполнили предыдущие шаги в этом учебном руководстве правильно, kextutil указывает, что kext является загружаемым и должным образом соединен.

No kernel file specified; using running kernel for linking.
MyKext.kext appears to be loadable (including linkage for on-disk libraries).

Куда пойти затем

Поздравления! Вы теперь записали, создали и подготовили свой собственный kext к загрузке. В следующем учебном руководстве в этом ряду, Создавая Драйвер устройства с XCode, Вы изучите, как создать драйвер Набора I/O, kext, позволяющий ядру взаимодействовать с устройствами. Если Вы не создаете Драйвер Набора I/O, можно перейти непосредственно к Отладке Расширения ядра с GDB, в котором Вы изучаете, как загрузить kext, отладить его и разгружаете его с установкой с двумя машинами.