Make driver linux src

Make driver linux src

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

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

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

Давайте в качестве примера рассмотрим соответствующие драйвера файловой системы FAT. На рис.2 показан весь процесс нашего эксперимента. Файлы с модулями будут fat.ko , vfat.ko и т.д., находящиеся в директории fat (в vfat для старых версий ядра) в /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 #include #include 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_* заполняется информация, относящаяся к модулю, которая будет использована как «подпись» модуля.

Читайте также:  Execute linux script file

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

Т.к. у нас есть код на языке 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 ($,) 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: $ -C $ SUBDIRS=$ modules clean: $ -C $ SUBDIRS=$ 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 загружен.

Читайте также:  Rtx 3060 driver linux

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

Источник

Как написать свой первый Linux device driver. Часть 3

В предыдущих статьях (один, два) мы определили понятие символьного устройства и написали простейший пример символьного драйвера. Последняя часть посвещена проверки его работоспособности. На Хабре уже есть примеры как можно протестировать драйвер, например: тык.

Я попытаюсь рассмотреть данный вопрос чуть подробнее, надеюсь, вам понравится.

Пожалуйста, если у вас есть мысли, что можно добавить/исправить, то жду ваших комментариев или писем в ЛС, спасибо.

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

Для того чтобы собрать наш модуль, нам понадобится написать маленький Makefile. Прочитать, что такое Makefile, можно тут: раз, два, три. Также я писал как-то пример Makefile для студентов, можно посомтреть тут: клик.

Если вкратце, то Makefile это набор инструкций для программы make, а make это утилита, автоматизирующая процесс преобразования файлов из одной формы в другую. После беглого знакомства с Makefile можно посмотреть на код:

obj-m += fake.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Давайте взгялнем на команду:

make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

Она начинается со смены каталога (в моем случае на: /lib/modules/4.4.0-93-generic/build), в этом каталоге находятся исходные тексты ядра, а также Makefile, который утилита make прочитает. Переменная M, позволяет указать где находится наш проект и вернуться назад, по указанному в нем пути. Т.е на самом деле мы используем другой Makefile, чтобы выполнить сборку нашего модуля.

Читайте также:  Linux apt delete program

Пишем в командной строке make и получаем вывод:

make -C /lib/modules/4.4.0-93-generic/build M=/home/alexey/Desktop/drivers/character modules make[1]: Entering directory '/usr/src/linux-headers-4.4.0-93-generic' CC [M] /home/alexey/Desktop/drivers/character/fake.o Building modules, stage 2. MODPOST 1 modules CC /home/alexey/Desktop/drivers/character/fake.mod.o LD [M] /home/alexey/Desktop/drivers/character/fake.ko make[1]: Leaving directory '/usr/src/linux-headers-4.4.0-93-generic'

После сборки, на выходе получился скомпилированный модуль fake.ko. Его то мы и будем загружать с помощью команды insmod.

Далее нужно выполнить следующую последовательность действий:

  1. Загрузить модуль в ядро
    Выполнить: sudo insmod fake.ko
  2. Проверить, с помощью команды dmesg, ожидаемый вывод модуля
    Пример: scull: register device major = 243 minor = 0
  3. Создать файл нашего устройства в файловой системе
    Пример: sudo mknod /dev/scull c 243 0
  4. Изменить права доступа
    Пример: sudo chmod 777 /dev/scull
#include #include #include #define DEVICE "/dev/scull" #define BUFF_SIZE 100 int main() < int fd; char ch, write_buf[BUFF_SIZE], read_buf[BUFF_SIZE]; fd = open(DEVICE, O_RDWR); if (!fd) return -1; printf("r - read, w - write\n"); scanf("%c", &ch); switch (ch) < case 'w': printf("enter data: "); scanf(" %[^\n]", write_buf); write(fd, write_buf, sizeof(write_buf)); break; case 'r': read(fd, read_buf, sizeof(read_buf)); printf("scull: %s\n", read_buf); break; >return 0; > 
  1. Компилируем: gcc test.c -o test
  2. Вызываем исполняемый файл: ./test
  3. Записываем в устройство: Hello world!
  4. Повторно вызываем исполняемый файл: ./test
  5. Считываем данные: scull: Hello world!

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

P.S. Если вы нашли неточности в статье, буду ждать ваших сообщений, спасибо!

Источник

Оцените статью
Adblock
detector