Меню Рубрики

Linux сборка модулей ядра

Часть 17. Сборка модулей. Дополнительные возможности

Серия контента:

Этот контент является частью # из серии # статей: Разработка модулей ядра Linux

Этот контент является частью серии: Разработка модулей ядра Linux

Следите за выходом новых статей этой серии.

В этой статье продолжается обсуждение процесса сборки и установки модулей ядра.

Сборка модуля из нескольких объектных файлов

Попробуем собрать модуль из основного файла mod.c и 3-х отдельно компилируемых файлов mfA.c, mfB.c и mfC.c, содержащих по одной отдельной функции, экспортируемой модулем. Полностью исходный код примеров представлен в архиве mobj.tgz в разделе «Материалы для скачивания».

Листинг 1. Главный файл: mod.c
Листинг 2. Один из трех подключаемых файлов: mfA.c

Файлы mfB.c и mfC.c полностью совпадают с mfA.c, только имена экспортируемых функций в них заменены, соответственно, на mod_func_2() и mod_func_3() .

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

Листинг 3. Вызывающий модуль mcall.c

В данном проекте наибольший интерес представляет файл сборки Makefile.

Листинг 4. Makefile для сборки одного из 2-х модулей (mobj) из 4-х объектных файлов

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

Это именно то, что требовалось: 4 отдельных объектных файла были собраны в единый файл модуля.

Рекурсивная сборка

Это вопрос, хотя и несвязанный непосредственно со сборкой модулей, очень часто возникает в проектах, работающих с модулями: как последовательно выполнить сборку одной и той же цели во всех включаемых каталогах? Хотелось бы иметь возможность собрать (или очистить по make clean ) всю иерархию каталогов проектов, не уточняя конкретные названия этих каталогов. Для такой цели можно использовать Makefile, приведенный в листинге 5.

Листинг 5. Сценарий рекурсивной сборки

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

Инсталляция модуля

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

  1. скопировать собранный файл модуля (*.ko) в его местоположение в иерархии модулей, часто это, например, каталог /lib/modules/`uname -r`/misc;
  2. обновить информацию о зависимостях модулей (в связи с добавлением нового), что делается вызовом утилиты depmod .

Но если в Makefile создаётся цель для инсталляции модуля, то обязательно должна быть создана и обратная цель для деинсталляции: лучше не иметь автоматической возможности инсталлировать модуль (и делать это вручную), чем автоматизировать процесс установки, не имея возможности удалить установленный модуль! Для деинсталляции модуля требуется:

  1. удалить файл модуля (*.ko) из его местоположения в иерархии модулей;
  2. обновить информацию о зависимостях модулей вызовом depmod .

В самом же файле Makefile эти цели могут быть записаны, как показано в листинге 6:

Листинг 6. Цели сборки: инсталляция и деинсталляция

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

Требуются ли собирать ядро?

Перед тем, как приступить к созданию модуля, программист (хотя бы для себя) должен ответить на следующие вопросы:

  • требуется ли собирать ядро;
  • следует ли освоить технику сборки ядра из исходного кода;
  • следует ли вообще уметь устанавливать ядро из исходного кода.

Сборка и установка нового ядра в современных версиях Linux не связана с какими-либо сложностями. Но из-за этого данное действие утратило свое «реальное» значение, превратившись в ложно понимаемый критерий профессионализма, и зачастую стало выполняться «просто так», без осознания ключевых принципов процесса сборки и установки ядра. Для сборки и тестирования модулей обязательная сборка самого ядра не требуется. Для работы с модулями достаточно наличия заголовочных файлов ядра (в точности соответствующих загруженной версии ядра!), а сам исходный программный код ядра не нужен.

Обычно заголовочные файлы, необходимые для разработки модулей, уже присутствуют в системе (это определяется предпочтениями авторов используемого Linux-дистрибутива). Но может оказаться, что исходный код ядра отсутствует, и в этом случае символьная ссылка /lib/modules/`uname -r`/build окажется неразрешённой, а каталог с исходным кодом ядра пустой.

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

В этом списке нас интересуют значения kernel-headers и kernel-devel. Здесь же показано точное требуемое соответствие версий пакетов той версии ядра, в которой ведётся разработка и компиляция модулей. Если пакета нет, то его необходимо установить (как показано ниже на примере одного из пакетов):

Листинг 7. Установка обязательных пакетов ядра

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

Листинг 8. Каталог разработки

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

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

Заключение

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

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

Источник

Сборка модулей ядра

Содержание

Модули ядра [ править ]

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

Модули могут подключаться к ядру по команде пользователя (modprobe, insmod) или автоматически при помощи udev, и быть выгружены либо самим ядром, либо командой rmmod.

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

О модулях и названиях [ править ]

Поскольку в репозитории может быть множество ядер, модули собираются особым способом: имеется пакет с исходными кодами модуля, и пакеты с модулями, собранным для конкретного ядра. При этом SRPM последних содержит только .spec и патчи, а исходные коды получает по сборочным зависимостям. Таким образом, для модуля module и варианта ядра flavour у нас имеются пакеты с именами

  • kernel-source-module — содержит только исходники
  • kernel-modules-module-flavour — модуль module, собранный для ядра flavour (например, kernel-modules-nvidia-std-def)

Поле release пакетов с модулями заполняется так: alt . . , где

  • — релиз собственно модуля, то есть, если мы обновили именно модуль, то это поле изменяется;
  • — версия ядра в формате (2^16) * major + (2^8) * mid + minor, то есть 2.6.25=132633. Не пугайтесь, это число рассчитывает скрипт, описанный позже;
  • — релиз пакета с ядром.

К примеру, модуль с nvidia для ядра kernel-image-std-def-2.6.25-alt8 будет называться kernel-modules-nvidia-std-def-173.14.12-alt1.132633.8.

Как собрать модуль локально [ править ]

Данная фаза нужна в первую очередь для тестирования модуля, и, в общем-то, необязательна, но полезна для понимания процесса.

Что нам нужно [ править ]

Кроме gcc, make и прочих стандартных сборочных вещей нам нужно kernel-headers-modules- (и всё что от него зависит). Этот пакет содержит ту часть исходных кодов, заголовочных файлов, make-файлов и скриптов, которые необходимы для сборки модулей для данного ядра.

Сборка [ править ]

Скачав и распаковав исходники модуля, мы обнаружим что просто make обычно не работает. Эта проблема специфична для Sisyphus/ALT Linux и состоит в том, что для сборки модуля необходимы заголовки ядра, которые ищутся в каталоге /lib/modules/ /build , но не могут быть найдены там, потому что в ALT Linux и Sisyphus доступ пользователям в /lib/modules/ запрещён.

Для того, чтобы обойти эту проблему, нужно переопределить переменную (обычно KERNELSOURCE или KSRC ) в Makefile . Далее запускаем сборку, например make KSRC=/usr/src/linux-2.6.25-std-def . Обычно модуль после этого собирается.

Собранный модуль можно попробовать загрузить с помощью insmod , или положить его к другим модулям ядра в /lib/modules/ и загрузить modprobe . Если модуль загрузился и работает, то можно переходить к следующей части.

Как собрать модуль правильно [ править ]

Почему предыдущий способ не является правильным? Потому что он недистрибутивен. Для нормальной сборки нам нужны:

  • знание git (крайне желательно хотя бы начальное знание!)
  • умение пользоваться gear и hasher
  • настроенный hasher
  • доступ на git.alt (для публикации результатов)
  • достаточно терпения

Шаблоны [ править ]

Поскольку править спеки каждого пакета с модулями для каждой версии ядра несколько глупо, была разработана схема, при которой для каждого модуля создается шаблон, а gear (при помощи директивы specsubst, в которой указывается flavour ядра) подгоняет этот шаблон к конкретному ядру (в том числе вычисляет релиз модуля). Остальная работа ложится на макрос %setup_kernel_module, который вычисляет все остальные параметры, нужные для сборки модуля: версию ядра, релиз ядра и релиз модуля. Сами шаблоны хранятся в git-репозитории, в котором есть множество веток, ветки с шаблонами называются template/module/distro, где module — это собственно название модуля (например, nvidia) а distro — это то, подо что мы собираем. Обычно это sisyphus, но, поскольку для разных бранчей шаблоны приходиться менять, можно установить поле distro в соответствующее значение. Обычно distro сейчас совпадает с именем бранча.

Подготовка рабочей директории [ править ]

Нам потребуются утилита km-create-tag для сборки модулей из пакета kernel-build-tools:

Для использования бранчей с шаблонами придётся их завести локально, например:

Сборка модуля из шаблона (с помощью gear-specsubst) [ править ]

Когда вы собираете локально в тестовых целях, удобно установить параметр gear.specsubst.kflavour с вашим ядром:

После этого модуль можно собрать с помощью команды:

Управление архитектурами, для которых собираются модули [ править ]

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

Начиная с kernel-build-tools-0.112-alt1, в нём реализована следующая функциональность:

В файле .gear/km-karch может сохраняться информация о архитектурах, для которых должен собираться модуль. Вот пример такого файла для virtualbox:

Такой файл описывает, что для ядра std-pae модуль должен собираться только на архитектуре i586, а для других ядер — для i586 и x86_64

Эта информация учитывается скриптом km-create-tag, но может быть переопределена при помощи ключа -a этого скрипта (не рекомендуется, так как эта информация не сохранится для следующего запуска km-create-tag и модуль для каких-то архитектур может оказаться молча потерян).

Для того, чтоб это работало, в спек файле должны быть строки:

А в .gear/rules файле строка:

Создание тегов для сборки на git.alt (схема с gear-specsubst) [ править ]

Например, для создания тега для модуля nvidia, собираемого для ядра std-def

Или, для создания тегов для всех модулей, можно сделать:

Сборка модулей на git.alt [ править ]

После этого можно запушить полученные бранчи и тэги на git.alt.

и добавить список модулей к последнему task’у (где предположительно уже добавлен на сборку соответствующий kernel-image):

Следует, однако, учитывать, что updatemodules и km-create-tag не затирают файл out/taglist и вам нужно делать это вручную.

Если же вы обновляете ядро, но не собираетесь обновлять шаблоны модулей, можно сделать:

$ ssh git.alt task add [номер задания] kmodules std-def

это добавит в задание (где предположительно уже добавлен на сборку соответствующий kernel-image) все модули, собранные для ядра std-def.

Некоторые моменты [ править ]

  • Если в репозитории: kernel-image-std-def-3.0.4-alt0.M60P.1.i586.rpm
  • Тогда в имени пакета: kernel-modules-emlog-std-def-0.51-alt2.196612.0.M60P.1.i586.rpm

В релиз модуля запаковывается версия + релиз ядра. СТРАШНО?

Пересобрать отдельно один модуль [ править ]

Допустим нужно пересобрать в репозитарий некий модуль без пересборки ядра и всех модулей.

Ветка kernel-modules-rt3070-std-def/sisyphus — должна быть вытянута последняя из http://git.altlinux.org/gears/

  1. Изменяем ветку template/rt3070/sisyphus, коммитим наши изменения
  2. km-create-tag -k std-def rt3070
  3. проверяем сборку чем-нибудь вроде: gear -t $(git describe) —hasher — hsh $TMP/

Сборка нового модуля [ править ]

Сборка kernel-source-module [ править ]

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

Редактируем по образу и подобию kernel-source-module.spec — обычно там надо заменить имя модуля, версию, описание и changelog, а сам процесс сборки обычно можно не трогать.

Далее собираем пакет при помощи gear. В результате в пакете должен оказаться всего один файл, а именно /usr/src/kernel/sources/kernel-source-module.tar.bz2

Обратите внимание на то, что некоторые пакеты с исходниками в своём имени содержат версию, например, kernel-source-kdbus-5.0.0.31-5.0.0.31-alt1. Это сделано для того, чтобы можно было иметь возможность собирать разные версии ядер с разными версиями модулей (например, новые модули не собираются с 2.6.18).

Создание нового шаблона [ править ]

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

где module — название вашего модуля.

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

Внимание, верхняя запись changelog должна оставаться неизменной и состоять их тех жутких макросов, из которых она состоит в любом модуле ядра в любом актуальном репозитории ALT

Как выложить свой модуль в репозиторий [ править ]

Выкладывание модулей ничем не отличается от выкладывания обычных пакетов.

Выкладываем собственно модуль:

Осталось собрать пакеты через git.alt.

Важное замечание: для того чтобы сборка прошла правильно, kernel-source-module должен быть собран до сборки kernel-modules-module.

Рекомендации по взаимодействию с мейнтейнерами ядер [ править ]

Для нормальной совместной работы рекомендуется:

  • При обновлении модуля обновлять сборки под максимальное количество ядер
  • Своевременно обновлять шаблоны в репозитории на git.alt
  • Оповестить мейнтейнеров ядер (в списке рассылки devel-kernel), о том что есть ваш модуль,
  • Настроить git remote на kernel-modules других мейнтейнеров,
  • В спеках kernel-modules- поле Packager установить в Kernel Maintainers team.

Про symvers и модули зависящие от других модулей [ править ]

Иногда бывает, что пакет с модулями, должен собираться под другой пакет с модулями. Так например просиходит с gspca и v4l. Для нормальной сборки нам нужно 2 вещи: во-первых, проставить правильно зависимости на headers (у v4l есть свои хедеры), во-вторых, нужно импортировать файл с symvers. В gscpca проблема решилась добавлением следующей строчки в %prep фазу пакета с модулем gspca:

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

  • Как поставить пароль на внешний жесткий диск mac os
  • Как поставить видео на рабочий стол mac os
  • Как поставить virtualbox на mac os
  • Как поставить mac os с флешки
  • Как поставить mac os на обычный комп