(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Драйверы устройств. Часть 2: Пишем в классе наш первый драйвер для Linux

Источник: rus-linux
Anil Kumar Pugalia; Перевод: Н.Ромоданов

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

Светлана и Пагс добрались в свой класс с опозданием и увидели, что их профессор уже начал читать лекцию. Светлана робко попросила разрешения войти. Раздраженный профессор Гопи ответил: "Входите! Вы, друзья, опять сегодня опоздали, и по какой причине"?

Пагс поспешно ответил, что они обсуждали именно ту тему, которую сегодня изучают в классе - драйверы устройств в Linux. Пагс был более, чем счастлив, когда профессор сказал: "Хорошо! Тогда что-нибудь скажите о динамической загрузке в Linux. Если вы справитесь, то я прощу вас обоих!". Пагс знал, что один из способов сделать профессора счастливым, это - покритиковать Windows.

Он объяснил: "Как известно, при обычной установке драйверов в Windows для того, чтобы их активировать, необходимо перезагрузить систему. А если это, предположим, действительно неприемлемо в случае, если это нужно делать на сервере? Вот где выигрывает Linux. В Linux можно загружать и выгружать драйверы на лету, и это активно используется сразу после загрузки системы. Кроме того, драйвер мгновенно отключается после его выгрузки. Это называется динамической загрузкой и выгрузкой драйверов в Linux ".

Это впечатлило профессора. "Хорошо! Идите на свои места, но больше не опаздывайте". Профессор продолжил лекцию: "Теперь, когда вы уже знаете, что такое динамическая загрузка и выгрузка драйверов, я, прежде, чем мы перейдем к написанию нашего первого драйверов, покажу вам, как загружать и выгружать драйвера".

Динамическая загрузка драйверов

Эти динамически загружаемые драйвера чаще всего называют модулями, которые собираются в виде отдельных модулей с расширением .ko (объект ядра). В каждой системе Linux в корне файловой системы (/) есть стандартное место для всех предварительно собранных модулей. Они организованы аналогично древовидной структуре исходных кодов ядра и находятся в директории /lib/modules/<kernel_version>/kernel, где <kernel_version> результат вывода системной команды uname -r (см.рис.1).

Рис.1: Предварительно собранные модули Linux

Чтобы динамически загружать и выгружать драйверы, воспользуйтесь следующими командами, которые находятся в директории /sbin и должны выполняться с привилегиями пользователя root:

  • lsmod - список модулей, загруженных в текущий момент
  • insmod <module_file> - добавление / загрузка указанного файла модуля
  • modprobe <module> - добавление / загрузка модуля вместе со всеми его зависимостями
  • rmmod <module> - удаление / выгрузка модуля

Давайте в качестве примера рассмотрим соответствующие драйвера файловой системы FAT. На рис.2 показан весь процесс нашего эксперимента. Файлы с модулями будут fat.ko, vfat.ko и т.д., находящиеся в директории fatvfat для старых версий ядра) в /lib/modules/`uname -r`/kernel/fs. Если они представлены в сжатом формате .gz, вам нужно будет распаковать их с помощью команды gunzip, прежде чем вы сможете выполнить операцию insmod.

Рис.2: Операции с модулями Linux

Модуль vfat зависит от модуля fat, так что первым должен быть загружен модуль fat.ko. Чтобы автоматически выполнить распаковку и загрузку зависимостей, воспользуйтесь командой modprobe. Обратите внимание, что когда вы пользуетесь командой modprobe, вы не должны в имени модуля указывать расширение .ko. Команда rmmod используется для выгрузки модулей.

Наш первый драйвер для Linux

Перед тем, как написать наш первый драйвер, давайте рассмотрим некоторые понятия. Драйвер никогда не работает сам по себе. Он похож на библиотеку, загружаемую из-за функций, которые будут вызваны из работающего приложения. Он написан на языке C, но в нем отсутствует функция main(). Кроме того, он будет загружаться / компоноваться с ядром, поэтому он должен компилироваться аналогично тому, как было откомпилировано ядро, и вы можете в качестве заголовочных файлов использовать только те, что есть в исходном коде ядра, а не из стандартного директория /usr/include.

Интересный факт, касающийся ядра, это то, что оно, как мы видим даже на примере нашего первого драйвера, представляет собой объектно-ориентированную реализацию на языке C. В любом драйвере есть конструктор и деструктор. Когда модуль успешно загружается в ядро, то вызывается конструктор модуля, а дескруктор модуля вызывается, когда команде rmmod удается успешно выгрузить модуль. Это в драйвере две обычные функции, разве что они называются init и exit , соответственно, и вызываются с помощью макросов module_init() и module_exit(), которые определены в заголовков ядра module.h.

/* ofd.c - Код нашего первого драйвера */
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
 
static int __init ofd_init(void) /* Конструктор */
{
    printk(KERN_INFO "Namaskar: ofd registered");
    return 0;
}
 
static void __exit ofd_exit(void) /* Дескруктор */
{
    printk(KERN_INFO "Alvida: ofd unregistered");
}
 
module_init(ofd_init);
module_exit(ofd_exit);
 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anil Kumar Pugalia ");
MODULE_DESCRIPTION("Our First Driver");

С учетом вышесказанного это полный код нашего первого драйвера; назовем его ofd.c. Обратите внимание, что отсутствует заголовок stdio.h (заголовок пользовательского пространства), вместо него мы используем аналог kernel.h (заголовок пространства ядра). Функция printk() эквивалентна функции printf(). Кроме того, для обеспечения совместимости версии модуля с ядром, в которое будет загружен модуль, добавлен заголовок version.h. С помощью макроса MODULE_* заполняется информация, относящаяся к модулю, которая будет использована как "подпись" модуля.

Сборка нашего первого драйвера

Т.к. у нас есть код на языке C, настало время его скомпилировать и создать файл модуля ofd.ko. Для этого мы используем систему сборки ядра. В приведенном ниже файле Makefile происходит обращение к системе сборки ядра из исходных кодов, а файл Makefile ядра, в свою очередь, обращается к файлу Makefile нашего нового драйвера с тем, чтобы собрать драйвер.

Чтобы собрать драйвер для Linux, у вас в системе должен быть исходный код ядра (или, по крайней мере, заголовки ядра). Предполагается, что исходный код ядра будет находиться в директории /usr/src/linux. Если в вашей системе он находится в каком-нибудь другом месте, то укажите это место в переменной KERNEL_SOURCE в файле Makefile.

# Makefile - makefile of our first driver
 
# if KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq (${KERNELRELEASE},)
    obj-m := ofd.o
# Otherwise we were called directly from the command line.
# Invoke the kernel build system.
else
    KERNEL_SOURCE := /usr/src/linux
    PWD := $(shell pwd)
default:
    ${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} modules
 
clean:
    ${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} clean
endif

Когда есть код на языке C (ofd.c) и готов файл Makefile, то все, что нам нужно сделать для сборки нашего первого драйвера (ofd.ko), это вызвать команду make.

$ make
make -C /usr/src/linux SUBDIRS=... modules
make[1]: Entering directory `/usr/src/linux'
  CC [M]  .../ofd.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      .../ofd.mod.o
  LD [M]  .../ofd.ko
make[1]: Leaving directory `/usr/src/linux'

Подведем итог

Как только у нас будет файл ofd.ko, мы в роли пользователя root или с помощью команды sudo выполним обычные действия.

# su
# insmod ofd.ko
# lsmod / head -10

Команда lsmod должна вам сообщить о том, что драйвер ofd загружен.

Пока студенты экспериментировали со своим первым модулем, прозвенел звонок, сообщивший об окончании урока. Профессор Гопи подвел итог: "В настоящий момент мы не увидели ничего, кроме того, что модуль lsmod сообщил о загрузке драйвера. Куда выводит информацию команда printk? Найдите это самостоятельно на лабораторных занятиях и познакомьте меня с своими выводами. Также учтите, что наш первый драйвер будет шаблоном для любого драйвера, который можно написать для Linux. Написание специализированных драйверов это всего лишь вопрос о том, чем будет заполнен конструктор и деструктор драйвера. Поэтому дальнейшее изучение будет представлять собой расширение данного драйвера с целью получить драйвер с конкретными функциональными возможностями".

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 15.06.2012 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Microsoft 365 Business Standard (corporate)
Microsoft Office 365 Персональный 32-bit/x64. 1 ПК/MAC + 1 Планшет + 1 Телефон. Все языки. Подписка на 1 год.
Microsoft Windows Professional 10, Электронный ключ
Microsoft Office 365 Профессиональный Плюс. Подписка на 1 рабочее место на 1 год
Microsoft 365 Business Basic (corporate)
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Безопасность компьютерных сетей и защита информации
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
OS Linux для начинающих. Новости + статьи + обзоры + ссылки
Программирование в AutoCAD
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100