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

    Добрый вечер, хаброчитатели!

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

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



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

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


    Для того чтобы собрать наш модуль, нам понадобится написать маленький 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.

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

    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 <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 - 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. Если вы нашли неточности в статье, буду ждать ваших сообщений, спасибо!
    • +28
    • 8,7k
    • 2
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 2
    • 0
      Спасибо. Было очень интересно. Жду продолжения, что-либо более сложное и реальное.
      • 0
        Осталось дело за малым, пишем маленькую программу, которая позволит просто считывать/записывать данные.

        А зачем? Для того же подойдут, например,
        echo Hello world | tee /dev/scull

        и
        cat /dev/scull


        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.