Кроме того, нашёл (в виде файлов) литературу:
a) Linux Device Drivers (Third edition) — J Corbet, A Rubini, Greg Hartman;
b) Essential Linux Device Drivers — S Ventkateswaran.
Здравствуйте, AlexGin, Вы писали:
AG>Тем не менее, остаются вопросы, которые следовало бы прояснить: AG>1) Отладка драйверов возможна только при помощи AG>
AG> pr_debug("...",...);
AG>
AG>при выводе в системный лог? AG>Или есть ещё какие-либо способы отладки кодов?
Можно ещё попытаться грузиться под 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".
Где-то можно об этом почитать подробнее?
Ну или загуглить по ключевым словам?
Возможно — это упростит и ускорит процесс отладки софта...
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, благодарю за столь развёрнутый ответ!
Там и читать — 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. Я здесь просто высказал предположение.
Для девайсов — "классически" пишут просто нормальный драйвер, который содержит в числе прочего 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).