Добрый вечер, хаброчитатели!
В предыдущих статьях (один, два) мы определили понятие символьного устройства и написали простейший пример символьного драйвера. Последняя часть посвещена проверки его работоспособности. На Хабре уже есть примеры как можно протестировать драйвер, например: тык.
Я попытаюсь рассмотреть данный вопрос чуть подробнее, надеюсь, вам понравится.
Пожалуйста, если у вас есть мысли, что можно добавить/исправить, то жду ваших комментариев или писем в ЛС, спасибо.
Сборка модуля ядра
Для того чтобы собрать наш модуль, нам понадобится написать маленький Makefile. Прочитать, что такое Makefile, можно тут: раз, два, три. Также я писал как-то пример Makefile для студентов, можно посомтреть тут: клик.
Если вкратце, то Makefile это набор инструкций для программы make, а make это утилита, автоматизирующая процесс преобразования файлов из одной формы в другую. После беглого знакомства с Makefile можно посмотреть на код:
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, чтобы выполнить сборку нашего модуля.
Пишем в командной строке 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.
Далее нужно выполнить следующую последовательность действий:
- Загрузить модуль в ядро
Выполнить:sudo insmod fake.ko
- Проверить, с помощью команды dmesg, ожидаемый вывод модуля
Пример:scull: register device major = 243 minor = 0
- Создать файл нашего устройства в файловой системе
Пример:sudo mknod /dev/scull c 243 0
- Изменить права доступа
Пример:sudo chmod 777 /dev/scull
Осталось дело за малым, пишем маленькую программу, которая позволит просто считывать/записывать данные.
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#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 - writen");
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: %sn", read_buf);
break;
}
return 0;
}
Проверка работоспособности:
- Компилируем:
gcc test.c -o test
- Вызываем исполняемый файл: ./test
- Записываем в устройство:
Hello world!
- Повторно вызываем исполняемый файл: ./test
- Считываем данные:
scull: Hello world!
На этом наше наше тестирование простого символьного драйвера завершено, теперь вы можете придумать новый функционал, реализовать и выполнить проерку самостоятельно:)
В конце предыдущей статье я проводил опрос, хочу сказать спасибо всем, кто принял в нем участие! В скором времени начну писать о процессе портирования драйверов устройств с одной версии ядра на другую.
P.S. Если вы нашли неточности в статье, буду ждать ваших сообщений, спасибо!
Автор: Alexey Ivanov