Главная » Статьи » Ядро | [ Добавить статью ] |
Ядро Linux относится к категории так называемых монолитных – это означает, что большая часть функциональности операционной системы называется ядром и запускается в привилегированном режиме. Этот подход отличен от подхода микроядра,
когда в режиме ядра выполняется только основная функциональность
(взаимодействие между процессами [inter-process communication, IPC],
диспетчеризация, базовый ввод-вывод [I/O], управление памятью), а
остальная функциональность вытесняется за пределы привилегированной
зоны (драйверы, сетевой стек, файловые системы). Можно было бы
подумать, что ядро Linux очень статично, но на самом деле все как раз
наоборот. Ядро Linux динамически изменяемое – это означает, что вы можете загружать в ядро дополнительную функциональность, выгружать функции из ядра и даже добавлять новые модули, использующие другие модули ядра. Преимущество загружаемых модулей заключается в возможности сократить расход памяти для ядра, загружая только необходимые модули (это может оказаться важным для встроенных систем). Linux – не единственное (и не первое) динамически изменяемое монолитное ядро. Загружаемые модули поддерживаются в BSD-системах, Sun Solaris, в ядрах более старых операционных систем, таких как OpenVMS, а также в других популярных ОС, таких как Microsoft® Windows® и Apple Mac OS X. Загружаемые
модули ядра имеют ряд фундаментальных отличий от элементов,
интегрированных непосредственно в ядро, а также от обычных программ.
Обычная программа содержит главную процедуру (main)в отличие от
загружаемого модуля, содержащего функции входа и выхода (в версии 2.6
эти функции можно именовать как угодно). Функция входа вызывается,
когда модуль загружается в ядро, а функция выхода – соответственно при
выгрузке из ядра. Поскольку функции входа и выхода являются
пользовательскими, для указания назначения этих функций используются
макросы Рисунок 1. Код простого загружаемого модуля. Версия
2.6 ядра Linux предоставляет новый, более простой метод создания
загружаемых модулей. После того как модуль создан, можно использовать
обычные пользовательские инструменты для управления модулями (несмотря
на изменения внутреннего устройства): Анатомия объектного кода модуля ядра Загружаемый модуль представляет собой просто специальный объектный файл в формате ELF (Executable and Linkable Format). Обычно объектные файлы обрабатываются компоновщиком, который разрешает символы и формирует исполняемый файл. Однако в связи с тем, что загружаемый модуль не может разрешить символы до загрузки в ядро, он остается ELF-объектом. Для работы с загружаемыми модулями можно использовать стандартные средства работы с объектными файлами (которые в версии 2.6 имеют суффикс .ko, от kernel object). Например, если вывести информацию о модуле утилитой objdump, вы обнаружите несколько привычных разделов, в том числе .text (инструкции), .data (инициализированные данные) и .bss (Block Started Symbol или неинициализированные данные). В
модуле также обнаружатся дополнительные разделы, ответственные за
поддержку его динамического поведения. Раздел .init.text содержит код Рисунок 2. Пример загружаемого модуля с разделами ELF Теперь, изучив основы загружаемых модулей ядра, давайте разберемся, как модули загружаются в ядро и как происходит управление ими внутри ядра. Жизненный цикл загружаемого модуля ядра Процесс загрузки модуля начинается в пользовательском пространстве с команды
Функция
Рисунок 3. Основные команды и функции, участвующие в загрузке и выгрузке модуля Во
время загрузки и выгрузки модуля подсистема модулей поддерживает
простой набор переменных состояния для обозначения статуса модуля. При
загрузке модуля он имеет статус Теперь давайте взглянем на внутренние функции для загрузки модуля (рисунок 4). При вызове функции ядра
Рисунок 4. Внутренний процесс загрузки модуля (упрощенно) Внутренние процессы загрузки модуля представляют собой анализ и управление модулями ELF. Функция Следующим шагом является ряд "санитарных проверок" загруженного образа (является ли ELF-файл допустимым? соответствует ли он текущей архитектуре? и так далее). После того как проверка пройдена, образ ELF анализируется и создается набор вспомогательных переменных для заголовка каждого раздела, чтобы облегчить дальнейший доступ к ним. Поскольку базовый адрес объектного файла ELF равен 0 (до перемещения), эти переменные включают соответствующие смещения в блок временной памяти. Во время создания вспомогательных переменных также проверяются заголовки разделов ELF, чтобы убедиться, что загружаемый модуль корректен. Дополнительные
параметры модуля, если они есть, загружаются из пользовательского
пространства в другой выделенный блок памяти ядра (шаг 4), и статус
модуля обновляется, чтобы обозначить, что он загружен ( В
предыдущих шагах разделы модуля загружались в память ядра (временную),
и было известно, какие из них используются постоянно, а какие могут
быть удалены. На следующем шаге (7) для модуля в памяти выделяется
окончательное расположение, и в него перемещаются необходимые разделы
(обозначенные в заголовках Затем
производится проход по оставшимся разделам и выполняются перемещения.
Этот шаг зависит от архитектуры и соответственно основывается на
вспомогательных функциях, определенных для данной архитектуры
(./linux/arch/<arch>/kernel/module.c). В конце очищается кэш
инструкций (поскольку использовались временные разделы .text),
выполняется еще несколько служебных процедур (очистка памяти временного
модуля, настройка sysfs) и, в итоге, модуль возвращает Выгрузка
модуля фактически представляет собой зеркальное отражение процесса
загрузки за исключением того, что для безопасного удаления модуля
необходимо выполнить несколько "санитарных проверок". Выгрузка модуля
начинается в пользовательском пространстве с выполнения команды Рисунок 5. Внутренний процесс выгрузки модуля (упрощенно). При вызове функции ядра К моменту вызова Оптимизация ядра для управления модулями Для
многих приложений необходима возможность динамической загрузки модулей,
но выгружать их не обязательно. Это позволяет ядру быть динамическим
при запуске (загрузка модулей в зависимости от обнаруженных устройств),
но неизменным во время работы. Если не требуется выгружать модули после
загрузки, можно сделать несколько усовершенствований для сокращения
количества кода, необходимого для управления модулями. В этом случае
можно отключить параметр настройки ядра Это
был лишь общий обзор процессов управления модулями в ядре. Лучшим
источником дополнительной информации об управлении модулями является
сам исходный код. Основные функции управления модулями содержатся в
./linux/kernel/module.c (и соответствующем файле заголовка
./linux/include/linux/module.h). Несколько функций, зависящих от
архитектуры, находятся в ./linux/arch/<arch>/kernel/module.c.
Наконец, функция автозагрузки ядра (которая автоматически загружает
модуль из ядра при необходимости) находится в файле
./linux/kernel/kmod.c. Эта функция включается при помощи параметра
настройки Источник: http://www.ibm.com/developerworks/ru/library/l-lkm/index.html | ||||||||||||||||||||||||||
Просмотров: 3657 | |
Всего комментариев: 0 | |
Операционные Системы
[61]
ОС Open Source
|
Мобильный Linux [26] |
Сравнение ОС [7] |
Статьи о Linux [16] |
Свободное ПО [10] |
Програмирование [6] |
Не для нубов [5] |
Ядро [13] |
Хранилище данных [9] |
Устройства [1] |
Установка/конфигурирование/планиров [16] |
Файловые системы [3] |
Управление, основанное на политиках [1] |
Управление инфраструктурой [0] |
Серверы [5] |
Биографии [6] |
Прочее [25] |