Программирование на уровне ядра и модули

#include <linux/module.h> #include <linux/kernel.h> int init_module(void) { printk("<1>Hello world 1.\n"); return 0; } void cleanup_module(void) { printk(KERN_ALERT "Goodbye world 1.\n"); } Makefile: obj-m += hello-1.o make -C /usr/src/linux-`uname -r` SUBDIRS=$PWD modules Если несколько файлов: obj-m += startstop.o startstop-objs := start.o stop.o

• Модуль – код, который может быть загружена или выгружена ядром по мере необходимости или вручную. Модули расширяют функциональные возможности ядра без необходимости перезагрузки системы.

• Драйверы устройств, позволяют ядру взаимодействовать с аппаратурой компьютера. Без поддержки модулей пришлось бы писать монолитные ядра и добавлять новые возможности прямо в ядро. При этом, после добавления в ядро новых возможностей, пришлось бы перезагружать систему

ЗАГРУЗКА МОДУЛЕЙ

• Возникает необходимость загрузки новых возможностей – модулей. Демон kmod вызывает утилиту modprobe, передавая: Название модуля или Универсальный идентификатор. Если передается универсальный идентификатор, то modprobe сначала пытается отыскать имя соответствующего модуля в файле /etc/modules.conf. Данному универсальному идентификатору соответствует файл модуля *.ko. Затем modprobe отыскивает файл /lib/modules/version/modules.dep и вызывает insmod, чтобы сначала загрузить необходимые для удовлетворения зависимостей модули, а затем и запрошенный модуль.

ИСПОЛНЕНИЕ МОДУЛЯ

Работа программы – main(). Модули – init_module() (или функция, определённая через вызов module_init). Функция запуска модуля, подготавливает его для последующих вызовов. Вторая точка входа в модуль – cleanup_module производит "откат" изменений. Любой модуль обязательно должен иметь функцию инициализации и функцию завершения.

ФУНКЦИИ, ДОСТУПНЫЕ ИЗ МОДУЛЯ

• Приложения: – Вызов функций, которые не определены в самой программе – На стадии компоновки разрешаются все внешние ссылки

• Модули: – проходят стадию компоновки, но только с ядром, и могут вызывать только те функции, которые экспортируются ядром • Разрешение ссылок на внешние символы производится утилитой insmod

ПРОСТРАНСТВО ПОЛЬЗОВАТЕЛЯ И ПРОСТРАНСТВО ЯДРА

• За доступ к ресурсам системы отвечает ядро, будь то видеоплата, жесткий диск или даже память • Программы часто конкурируют между собой за доступ к тем или иным ресурсам • Ядро должно обслужить конкурирующие запросы, и "выстроить" их в порядке очередности • К тому же сам центральный процессор может работать в различных режимах • Каждый из режимов имеет свою степень "свободы" действий • Процессор Intel 80386 имеет четыре таких режима, которые часто называют «кольцами» • Unix использует только два из них: наивысший (привилегированный режим) и низший (пользовательский режим).

• Как правило, программа обращается к библиотечным функциям, находясь в пользовательском режиме • Затем библиотечные функции обращаются к системным вызовам • Системные вызовы происходят в привилегированном режиме (printf => write) • Системный вызов завершает работу – возвращает управление.

• Ядро тоже имеет свое собственное адресное пространство • Поскольку модуль по сути является частью ядра, то он так же работает в адресном пространстве ядра. • Есть операционные системы, в основе которых лежит микроядро • В таких ОС каждый модуль получает свое адресное пространство.

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

ПРОСТРАНСТВА ИМЕН???

УПРАВЛЕНИЕ УСТРОЙСТВАМИ

В Linux каждое аппаратное устройство представлено псевдофайлом (файлом устройства) в каталоге /dev. Этот файл обеспечивает средства взаимодействия с аппаратурой.

Работу по подключению и удалению устройств выполняет ядро системы. Изменения состояния устройств (подключение нового или удаление существующего) должны быть при этом видимы в пользовательском пространстве. При подключении новых устройств они должны тут же корректно настраиваться и (при необходимости) опознаваться пользовательскими приложениями. Файлы устройств (device nodes) в каталоге /dev обеспечивают доступ к соответствующим устройствам. В данном каталоге находятся файлы только тех устройств, которые в настоящий момент подключены к системе. Каждое устройство имеет свой соответствующий файл. Если устройство отключается от системы — данный файл удаляется.

Содержимое каталога /dev хранится на виртуальной файловой системе и все файлы, находящиеся в нем, создаются при каждом запуске системы. Модифицированные или созданные вручную файлы не сохраняются после перезагрузки. Файлы и каталоги, которые необходимо сохранить или которые всегда должны присутствовать в каталоге /dev, независимо от состояния соответствующего устройства, необходимо помещать в каталог /lib/udev/devices. При запуске системы содержимое данного каталога копируется в /dev.

Наши рекомендации