Символьная таблица ядра

Предыдущая  Содержание  Следующая V*D*V

Мы видели, как insmod разрешает неопределённые символы на таблицу публичных символов ядра. В таблице содержатся адреса глобальных объектов ядра - функций и переменных, которые необходимы для выполнения модуляризованных драйверов. При загрузке модуля любой символ, экспортируемый модулем, становится частью таблицы символов ядра. В обычном случае модуль предоставляет свою функциональность без необходимости экспортировать любые символы вообще. Однако, вам необходимо экспортировать символы, если другие модули могут получить выгоду от их использования.

 

Новые модули могут использовать символы, экспортированные вашим модулем, и вы можете накладывать новые модули поверх других модулей (то есть создавать стек модулей). Исходный код основного ядра также использует наложение модулей: файловая система ms-dos опирается на символы, экспортируемые модулем fat, а каждое устройство ввода модуля USB опирается на модули usbcore и input. Стек модулей полезен в сложных проектах. Если новые абстракции реализованы в виде драйвера устройства, он может предложить подключение для конкретной аппаратной реализации. Например, набор драйверов video-for-linux разделён внутри общего модуля, который экспортирует символы, используемые более низкоуровневыми драйверами устройств для конкретного оборудования. Вы загружаете общий видео модуль и специфичные модули для вашего установленного оборудования в соответствии с настройками. Поддержка параллельных портов и широкий спектр подключаемых устройств обрабатывается таким же образом, как и в подсистеме USB ядра. Стек подсистемы параллельного порта показан на Рисунке 2-2; Стрелки показывают связи между модулями и с интерфейсом программирования ядра.

 

Рисунок 2-2. Стек модулей драйвера параллельного порта

Рисунок 2-2. Стек модулей драйвера параллельного порта

 

 

При использовании стековых модулей полезно использовать утилиту modprobe. Как описано выше, функции modprobe во многом такие же, как у insmod, но она также загружает любые другие модули, которые необходимы для модуля, который вы хотите загрузить. Таким образом, одна команда modprobe может иногда заменить несколько вызовов insmod (хотя insmod всё равно необходима при загрузке собственных модулей из текущего каталога, так как modprobe просматривает только стандартные каталоги для установленных модулей). Использование стека, чтобы разделить модули на несколько слоёв, может помочь сократить время разработки за счёт упрощения каждого слоя. Это похоже на разделение между механизмом и политикой, которое мы обсуждали в Главе 1.

 

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

 

EXPORT_SYMBOL(name);

EXPORT_SYMBOL_GPL(name);

 

Каждый из вышеописанных макросов делает данный символ доступным за пределами модуля. Версия _GPL делает символ доступным только для GPL-лицензированных модулей. Символы должны быть экспортированы в глобальной части файла модуля, вне какой-либо функции, потому что макросы заменяются на объявление переменной специального назначения, которая, как ожидается, будет доступна глобально. Эта переменная запоминается в специальной части исполняемого модуля (“секции ELF“), которая используется ядром во время загрузки, чтобы найти переменные, экспортируемые модулем. (Заинтересованные читатели могут заглянуть в <linux/module.h> для деталей, хотя детали не нужны, чтобы всё работало.)

Предыдущая  Содержание  Следующая