Разработка драйверов ядра Linux
От: AlexGin Беларусь  
Дата: 30.01.24 06:58
Оценка:
Доброго времени суток, уважаемые коллеги!

Я теперь занялся изучением вопроса по разработке драйверов ядра Linux.
Это актуально для наших новых проектов.

Погуглив на данную тему, я нашёл ссылки:

https://jvgd.medium.com/how-to-write-a-device-driver-76d0584a4be3
https://www.apriorit.com/dev-blog/195-simple-driver-for-linux-os
https://habr.com/ru/companies/timeweb/articles/724282/
также имеются ещё ссылочки на "хабр" (их дегко нагуглить).

На гит-хабе есть интересные примеры:
https://github.com/d0u9/Linux-Device-Driver
Успешно сделал около семи примеров из данного сайта.

Кроме того, нашёл (в виде файлов) литературу:
a) Linux Device Drivers (Third edition) — J Corbet, A Rubini, Greg Hartman;
b) Essential Linux Device Drivers — S Ventkateswaran.

Нашёл исходники:
https://www.kernel.org/
https://www.kernel.org/releases.html
https://www.kernel.org/category/releases.html

Тем не менее, остаются вопросы, которые следовало бы прояснить:
1) Отладка драйверов возможна только при помощи
   pr_debug("...",...);

при выводе в системный лог?
Или есть ещё какие-либо способы отладки кодов?

2) Общение кодов драйвера с приложениями usermode — как я понимаю через модель дискового обмена Linux:
   cat /dev/xxxx

   ioctl(...); 
   fopen(...); и т.д.

Или же есть другие способы обмена данными с процессами пользователя?

3) Я в курсе — что есть драйвера, которые можно динамически запускать (загружать) и удалять —
insmod our_driver.ko
rmmod our_driver

Но всё же — как принято запускать драйвера ядра? Например — при помощи systemd?
Или как-то иначе?

Заранее благодарю за любые мысли!
Отредактировано 30.01.2024 10:11 AlexGin . Предыдущая версия . Еще …
Отредактировано 30.01.2024 6:59 AlexGin . Предыдущая версия .
Re: Разработка драйверов ядра Linux
От: aik Австралия  
Дата: 30.01.24 23:11
Оценка: 4 (1) +1
Здравствуйте, AlexGin, Вы писали:

AG>Тем не менее, остаются вопросы, которые следовало бы прояснить:

AG>1) Отладка драйверов возможна только при помощи
AG>
AG>   pr_debug("...",...);
AG>

AG>при выводе в системный лог?
AG>Или есть ещё какие-либо способы отладки кодов?

Всяческие трейспоинты:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/trace

Можно ещё попытаться грузиться под KVM+QEMU с включённым gdbstub в QEMU (-s), и при определённой удаче можно даже символы из vmlinux подгрузить в gdb.

AG>2) Общение кодов драйвера с приложениями usermode — как я понимаю через модель дискового обмена Linux:

AG>
AG>   cat /dev/xxxx
AG>

AG>
AG>   ioctl(...); 
AG>   fopen(...); и т.д.
AG>

AG>Или же есть другие способы обмена данными с процессами пользователя?

Этих мало что ли? Можно ещё mmap на этих девайсах делать, или создавать внутри другие fd (file descriptor) и возвращать через ioctl. Ещё есть sysfs. Сетевые драйверы PCI устройств вообще ничего в /dev не создают, там свои syscalls.

AG>3) Я в курсе — что есть драйвера, которые можно динамически запускать (загружать) и удалять —

AG>
AG>insmod our_driver.ko
AG>rmmod our_driver
AG>


insmod просто грузит один конкретный .ko файл, и кмк без зависимостей. modprobe ищет и грузит модуль по имени со всеми зависимостями для запущенного ядра.

AG>Но всё же — как принято запускать драйвера ядра? Например — при помощи systemd?


хз. Наверное systemd делает и это теперь, парней уже не остановить — подменяют всё

AG>Или как-то иначе?


Загрузка драйвера и bind к устройствам — разные операции. Обычно драйвер сразу цепляется к девайсам, но какой нибудь vfio-pci — нет. У драйверов есть ноды bind/unbind в sysfs. Например, отцепить драйвер от девайса — "echo 0000:02:00.0 > /sys/bus/pci/drivers/xhci_hcd/unbind", прицепить назад — "echo 0000:02:00.0 > /sys/bus/pci/drivers/xhci_hcd/bind".
Re[2]: Разработка драйверов ядра Linux
От: AlexGin Беларусь  
Дата: 01.02.24 16:46
Оценка:
Здравствуйте, aik, Вы писали:

aik>Всяческие трейспоинты:

aik>https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/trace

Где-то можно об этом почитать подробнее?
Ну или загуглить по ключевым словам?
Возможно — это упростит и ускорит процесс отладки софта...

aik>Можно ещё попытаться грузиться под KVM+QEMU с включённым gdbstub в QEMU (-s), и при определённой удаче можно даже символы из vmlinux подгрузить в gdb.


То есть — некая эмуляция целевой OS на компьютере разработчика? Верно я это понимаю?

aik>Этих мало что ли? Можно ещё mmap на этих девайсах делать, или создавать внутри другие fd (file descriptor) и возвращать через ioctl. Ещё есть sysfs. Сетевые драйверы PCI устройств вообще ничего в /dev не создают, там свои syscalls.


Может и совсем даже не мало. Просто я полюбопытствовал. Не факт, что это для меня будет иметь практический счысл.

AG> Я в курсе — что есть драйвера, которые можно динамически запускать (загружать) и удалять —

AG>
AG>insmod our_driver.ko
AG>rmmod our_driver
AG>


aik>insmod просто грузит один конкретный .ko файл, и кмк без зависимостей.

aik>modprobe ищет и грузит модуль по имени со всеми зависимостями для запущенного ядра.

Спасибо, буду в курсе!

AG>Но всё же — как принято запускать драйвера ядра? Например — при помощи systemd?

aik>хз. Наверное systemd делает и это теперь, парней уже не остановить — подменяют всё

Я совсем не уверен — делеет ли запуск драйверов подсистема systemd. Я здесь просто высказал предположение.
Как рекомендуется запускать драйвера в Linux, и как это принято классически делать?

aik>Загрузка драйвера и bind к устройствам — разные операции. Обычно драйвер сразу цепляется к девайсам, но какой нибудь vfio-pci — нет. У драйверов есть ноды bind/unbind в sysfs. Например, отцепить драйвер от девайса — "echo 0000:02:00.0 > /sys/bus/pci/drivers/xhci_hcd/unbind", прицепить назад — "echo 0000:02:00.0 > /sys/bus/pci/drivers/xhci_hcd/bind".


Спасиьо, уважаемый aik, благодарю за столь развёрнутый ответ!
Отредактировано 01.02.2024 16:49 AlexGin . Предыдущая версия .
Re[3]: Разработка драйверов ядра Linux
От: aik Австралия  
Дата: 02.02.24 03:49
Оценка: 10 (2) +1
Здравствуйте, AlexGin, Вы писали:

aik>>Всяческие трейспоинты:

aik>>https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/trace
AG>Где-то можно об этом почитать подробнее?

Там и читать — ftrace.rst, к примеру. У меня на ноуте в /sys/kernel/debug/tracing/events куча всякого, к примеру.

aik>>Можно ещё попытаться грузиться под KVM+QEMU с включённым gdbstub в QEMU (-s), и при определённой удаче можно даже символы из vmlinux подгрузить в gdb.

AG>То есть — некая эмуляция целевой OS на компьютере разработчика? Верно я это понимаю?

Это запуск линукса в виртуальной машине под QEMU+KVM в качестве гипервизора, который имеет gdb интерфейс наружу. Обычно отлаживают пользовательские процессы под gdb, а в этом случае можно отлаживать vmlinux тем же gdb. Можно и без KVM, кстати, только относительно медленно.

AG>>Но всё же — как принято запускать драйвера ядра? Например — при помощи systemd?

aik>>хз. Наверное systemd делает и это теперь, парней уже не остановить — подменяют всё
AG>Я совсем не уверен — делеет ли запуск драйверов подсистема systemd. Я здесь просто высказал предположение.

Ха, он тоже может https://www.freedesktop.org/software/systemd/man/latest/systemd-modules-load.service.html

AG>Как рекомендуется запускать драйвера в Linux, и как это принято классически делать?


Самому стало интересно хз про классику.

Для девайсов — "классически" пишут просто нормальный драйвер, который содержит в числе прочего struct pci_driver::id_table — id девайсов, которые драйвер поддерживает (у USB аналогично). Поищи в ядре e1000_pci_tbl для популярной сетевухи Intel e1000, к примеру. Ядро знает из этих таблиц какие драйвера для чего и, когда сканирует шину (PCI, USB), пробует эти драйверы. Чтоб не пробовать прямо уж все драйверы в системе при каждой загрузке, в initramdisk (маленький rootfs для старта) добавляются только актуальные драйверы.

Если это не драйвер устройства, а прочее — tun, vfat, nf_nat и так далее — то сервисы (из systemd) будут грузить что посчитают нужным (хотя я вот не уверен кто именно грузит файловые системы при втыкании usb-storage, systemd или само ядро?), а modprobe догрузит зависимости (которые вычисляет тулза kdepmod, результат в /lib/modules/$(uname -r)/modules.softdep).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.