вторник, 13 февраля 2018 г.

Как написать простой драйвер в Linux?

Как написать простой драйвер в Linux?

/* Заголовочные файлы */
#include <linux/init.h>
#include <linux/module.h>
/* Загрузка драйвера */
static int driver_init(void)
{
  printk(KERN_ALERT "Driver Loaded!\r\n");
  return 0;
}
/* Выгрузка драйвера*/
static void driver_unload(void)
{
  printk(KERN_ALERT "Driver Unloaded!\r\n");
}
/* Инициализация call-back на функционал */
module_init(driver_init);
module_exit(driver_unload);

можно заметить что программирование драйверов под Linux,
похоже с программирование драйверов под Windows, похоже тем, что используются все те же call-back механизмы...

###
назовем этот файл main.c

###
Создаем файл Makefile (Будьте внимательные к регистру, для make - это чувствительно!) nano Makefile
т.к у нас модуль называется main.c



Содержимое Makefile:

obj-m += main.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
Вывод:

make[1]: вход в каталог «/usr/src/linux-headers-4.9.0-5-amd64»
  Building modules, stage 2.
  MODPOST 1 modules
make[1]: выход из каталога «/usr/src/linux-headers-4.9.0-5-amd64»
root@myDebian:/home/ru/C++/test# rm -rf *.o *.ko *.mod.*
root@myDebian:/home/ru/C++/test# make
make -C /lib/modules/4.9.0-5-amd64/build M=/home/ru/C++/test modules
make[1]: вход в каталог «/usr/src/linux-headers-4.9.0-5-amd64»
  CC [M]  /home/ru/C++/test/main.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/ru/C++/test/main.mod.o
  LD [M]  /home/ru/C++/test/main.ko
make[1]: выход из каталога «/usr/src/linux-headers-4.9.0-5-amd64»

Драйвер успешно собрался! Как проверить работу?...

Выполнить :
  insmod ./main.ko
Чтобы увидить отладочные сообщения драйвера из ядра необходимо воспользоваться утилитой dmesg
Набираем dmesg
[45677.526885] Driver Loaded!
[45995.205288] Driver Unloaded!

###
Если попытаться загрузить драйвер еще раз  insmod ./main.ko, вы получите ошибку:
insmod: ERROR: could not insert module ./main.ko: File exists - это связанно с тем что модуль драйвера уже был загружен чтобы исправить эту ошибку
необходимо выполнить несколько команд:
Проверить есть ли модуль в памяти, набрав lsmod | grep main
После этого произвести удаление, выполнив
rmmod main

Замечания:
 Определение KERN_ALERT - это приоритет сообщения. (* Приоритет -
это просто строка, например, <1>, которая добавляется в начало строки форматирования
printk. Обратите внимание на отсутствие запятой после KERN_ALERT; добавление запятой
здесь - это частая и раздражающая опечатка (которая, к счастью, улавливается
компилятором.)), я рекомендую использовать KERN_INFO вместо KERN_ALERT.

В данном файле main.c остутствует информация о лицензии, поэтому при компиляции компилятор сам добавит необходимую информацию, чтобы добавить
информацию о лицензии необходимо в заголовке файла опредилить MODULE_LICENSE("GPL"); Снизу приводится список доступных лицензий...

/*
 * The following license idents are currently accepted as indicating free
 * software modules
 *
 * "GPL" [GNU Public License v2 or later]
 * "GPL v2" [GNU Public License v2]
 * "GPL and additional rights" [GNU Public License v2 rights and more]
 * "Dual BSD/GPL" [GNU Public License v2
 * or BSD license choice]
 * "Dual MIT/GPL" [GNU Public License v2
 * or MIT license choice]
 * "Dual MPL/GPL" [GNU Public License v2
 * or Mozilla license choice]
 *
 * The following other idents are available
 *
 * "Proprietary" [Non free products]
 *
 * There are dual licensed components, but when running with Linux it is the
 * GPL that is relevant so this is a non issue. Similarly LGPL linked with GPL
 * is a GPL combined work.
 *
 * This exists for several reasons
 * 1. So modinfo can show license info for users wanting to vet their setup
 * is free
 * 2. So the community can ignore bug reports including proprietary modules
 * 3. So vendors can do likewise based on their own policies
 */

Можно так-же указать информацию об авторе и о самом драйвере:

/*
 * Or with defines, like this:
 */

MODULE_AUTHOR(DRIVER_AUTHOR); /* Who wrote this module? */
MODULE_DESCRIPTION(DRIVER_DESC) /* What does this module do */

/*
 *  This module uses /dev/testdevice.  The MODULE_SUPPORTED_DEVICE macro might
 *  be used in the future to help automatic configuration of modules, but is
 *  currently unused other than for documentation purposes.
 */
MODULE_SUPPORTED_DEVICE("testdevice");

вот так в простейшем случае может выглядить написание драйвреов под Linux.

Комментариев нет:

Отправить комментарий