linux kernel modules

Модули и драйверы Linux Kernel: установка, сборка и работа

Когда в Linux не работает Wi-Fi, VirtualBox ругается на vboxdrv, а сборка модуля внезапно упирается в kernel headers, проблема почти всегда не в “сломавшемся Linux”, а в том, как ядро, драйвер и модуль связаны между собой. Именно здесь чаще всего и возникает путаница: что загружается, что компилируется, что уже встроено в ядро, а что нужно подключать отдельно.

Ниже — практическое объяснение без воды: что такое kernel modules и drivers, как их включать и выгружать, когда нужен свой модуль, зачем нужны headers, чем отличаются insmod и modprobe, и что делать при типичных ошибках вроде kernel driver not installed.


Что такое Linux Kernel Modules и зачем они нужны

Определение модулей ядра

Linux kernel module — это загружаемый фрагмент кода ядра, который можно подключить во время работы системы без полной пересборки kernel. Обычно модуль имеет расширение .ko и хранится в каталоге /lib/modules/$(uname -r)/.

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

ПараметрВстроено в ядроЗагружается как модуль
Когда доступноСразу после загрузки ядраПо требованию или при старте системы
ГибкостьНижеВыше
Нужна пересборка ядраЧасто даОбычно нет
Выгрузка без перезагрузкиНетЧасто да
Типичный сценарийКритичные для загрузки компонентыДрайверы, FS, сетевые подсистемы

Преимущества модульной архитектуры

Главный плюс модулей — гибкость. Ядро не обязано тащить в память всё подряд: оно подгружает только то, что нужно конкретной системе и конкретному железу.

  • не нужно пересобирать всё ядро ради одной функции;
  • многие модули можно загрузить и выгрузить без reboot;
  • проще тестировать драйверы и обновлять отдельные компоненты;
  • меньше лишнего кода в памяти на минимальных системах и серверах.

Но есть и ограничение: модуль жёстко зависит от ABI/версии ядра, конфигурации сборки и наличия подходящих headers. Поэтому модуль, собранный под одно kernel, нередко не работает на другом.

Примеры использования

Самый частый сценарий — драйверы устройств. Сетевая карта, Wi-Fi-адаптер, GPU, USB-устройство, виртуальный сетевой интерфейс — всё это часто работает через модуль ядра.

Другие примеры: файловые системы вроде ext4, btrfs или zfs-модулей, VPN и firewall-подсистемы, а также виртуализация. Если вы разбираетесь с графикой под Linux, полезно отдельно посмотреть, как устроен стек AMDGPU в Linux, потому что там хорошо видно связку “ядро + модуль + userspace”.

Модуль ядра — это не “что-то отдельное от Linux”, а штатный механизм расширения kernel без полной пересборки системы.


Как работать с модулями Linux Kernel

Просмотр загруженных модулей

Базовая команда — lsmod. Она показывает, какие модули уже загружены, сколько памяти они занимают и кто от кого зависит.

lsmod

Для поиска конкретного модуля удобнее фильтровать вывод:

lsmod | grep vbox
lsmod | grep nvidia
lsmod | grep amdgpu

Если нужно понять не просто “загружен ли модуль”, а где он лежит и какие зависимости у него есть, полезнее команда modinfo:

modinfo vboxdrv
modinfo amdgpu

Включение (enable) модуля

Обычно модуль подключают через modprobe. Это основной и безопасный способ, потому что команда умеет искать модуль в стандартных каталогах и автоматически подтягивать зависимости.

sudo modprobe module_name

Например:

sudo modprobe loop
sudo modprobe vboxdrv

Если модуль должен загружаться автоматически при старте, его имя обычно добавляют в конфигурацию автозагрузки, например в /etc/modules-load.d/custom.conf.

echo vboxdrv | sudo tee /etc/modules-load.d/virtualbox.conf
КомандаЧто делаетКогда использовать
insmod file.koЗагружает конкретный файл модуляТестирование своего модуля
modprobe nameИщет модуль по имени и тянет зависимостиПовседневная работа в системе
rmmod nameВыгружает модульБыстрое удаление без зависимостей
modprobe -r nameУдаляет модуль с учётом зависимостейПредпочтительный способ выгрузки

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

Отключение и удаление

Для выгрузки модуля можно использовать rmmod, но в большинстве случаев удобнее modprobe -r, потому что он аккуратнее работает с зависимостями.

sudo modprobe -r module_name
sudo rmmod module_name

Если модуль “занят”, это значит, что его использует процесс, устройство или другой модуль. Типичный пример — сетевой драйвер, через который у вас прямо сейчас идёт соединение.

Для диагностики почти всегда нужен dmesg. Именно там видны ошибки инициализации, несовместимости версии, проблемы подписи модуля, missing symbols и отказ загрузки.

dmesg | tail -n 50
dmesg | grep -i module
dmesg | grep -i vbox
Практический сценарий выбора

  • если ставите стандартный модуль из репозитория — используйте modprobe;
  • если тестируете свой только что собранный .ko — сначала insmod, затем проверка через dmesg;
  • если модуль нужен после каждой загрузки — добавляйте автозагрузку через modules-load.d или пакетный механизм дистрибутива.

Сборка собственного kernel module

Когда это нужно

Свой kernel module обычно собирают в трёх случаях: под устройство нет штатного драйвера, вы разрабатываете или тестируете свой драйвер, либо используете сторонний код вне дерева ядра — out-of-tree module.

На практике это актуально для нестандартного железа, исследовательских проектов, embedded-систем и некоторых корпоративных драйверов. Для обычного десктопа собственная сборка нужна редко, но именно она часто всплывает при установке VirtualBox, проприетарных драйверов или DKMS-пакетов.

Базовый процесс сборки

Минимальная схема выглядит так: пишется исходник на C, создаётся Makefile, затем модуль собирается против текущего дерева headers, после чего загружается в ядро.

// hello.c
#include <linux/init.h>
#include <linux/module.h>

static int __init hello_init(void) {
    pr_info("hello module loaded\n");
    return 0;
}

static void __exit hello_exit(void) {
    pr_info("hello module unloaded\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Example");
MODULE_DESCRIPTION("Simple Linux kernel module");
# Makefile
obj-m += hello.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
sudo insmod hello.ko
dmesg | tail
sudo rmmod hello

Ключевой момент здесь — путь /lib/modules/$(uname -r)/build. Он должен указывать на корректно установленные headers или подготовленное дерево сборки ядра.

Требования (headers)

Для сборки почти всегда нужны:

  • компилятор gcc или совместимый toolchain;
  • make;
  • kernel headers под текущую версию ядра;
  • иногда — binutils, elfutils, dkms.

Самая частая ошибка здесь — несоответствие версий. У вас может быть запущено ядро 6.x.y-custom, а headers установлены для другой версии. В итоге модуль либо не соберётся, либо загрузится с ошибкой invalid module format.

Что подтверждено, а что часто путают

  • Подтверждено: headers должны совпадать с текущим ядром, против которого идёт сборка.
  • Подтверждено: модуль можно собрать отдельно, без пересборки всего kernel.
  • Частая ошибка: пакет kernel-headers сам по себе не всегда равен полному набору файлов для внешней сборки в конкретном дистрибутиве.
  • Частая ошибка: “если модуль собрался, значит точно заработает” — нет, он ещё должен корректно загрузиться и пройти проверку зависимостей, символов и подписи.

Где помогает DKMS: DKMS пересобирает внешний модуль автоматически после обновления ядра. Это особенно полезно для VirtualBox, NVIDIA и других сторонних драйверов, которые ломаются после kernel update.

Сборка своего модуля — это несложно по шагам, но чувствительно к версии ядра, toolchain и headers.


Linux Kernel Drivers: что это и как работают

Разница между драйвером и модулем

Драйвер и модуль — не одно и то же. Драйвер — это логика работы с устройством. Модуль — это форма доставки кода в ядро.

На практике драйвер может быть:

  • встроен прямо в ядро;
  • собран как загружаемый модуль;
  • состоять из нескольких компонентов, где часть работает в kernel, а часть — в userspace.

Поэтому фраза “установить драйвер” в Linux часто означает именно “поставить пакет с модулем ядра и служебными компонентами”.

Типы драйверов

Базово драйверы делят на несколько групп:

  • символьные — последовательный доступ к данным, терминалы, датчики, специальные интерфейсы;
  • блочные — диски, SSD, NVMe, loop-устройства;
  • сетевые — Ethernet, Wi-Fi, виртуальные интерфейсы, туннели;
  • графические — GPU и DRM/KMS-стек;
  • виртуализационные — VirtualBox, VMware, guest additions, paravirtual devices.
Тип драйвераПримерКогда актуален
СетевойEthernet, Wi-FiНет сети, не поднимается интерфейс
БлочныйNVMe, SATA, loopНе виден диск или том
Символьный/dev устройстваРабота со спецоборудованием
Графическийamdgpu, nouveau, nvidiaПроблемы с ускорением и выводом
ВиртуализационныйvboxdrvНе стартуют VM

Как ядро взаимодействует с устройствами

Ядро обнаруживает устройство через шины и подсистемы вроде PCI, USB, ACPI или platform bus, сопоставляет ID устройства с подходящим драйвером и инициализирует его. Дальше драйвер уже связывает hardware с остальными подсистемами kernel.

Если упростить цепочку, она выглядит так:

hardware → bus/ID → kernel driver → subsystem → userspace

Именно поэтому проблема может быть не только в самом драйвере. Устройство может определяться BIOS/UEFI некорректно, нужный модуль может быть blacklisted, может не хватать firmware, а userspace-утилиты могут сообщать ошибку так, будто “драйвера вообще нет”.

Если вам интересны изменения в самом ядре, полезно сравнивать поведение драйверов с тем, что приносит свежий kernel. Для контекста можно посмотреть, что менялось в Linux 6.18 и какие аппаратные улучшения добавлялись в новых релизах вроде Linux 6.19.

Можно ли написать драйвер без модулей? Да. Его можно встроить прямо в ядро при конфигурации и сборке kernel. Но для разработки, тестирования и сопровождения внешний модуль обычно удобнее.


Ошибки драйверов и их решение

kernel driver not installed linux

Эта ошибка почти никогда не означает буквально, что “в системе нет драйвера”. Обычно она указывает на один из четырёх сценариев: модуль не загружен, модуль не собран под текущее ядро, отсутствуют headers, либо сломана цепочка зависимостей после обновления системы.

Пошаговая проверка выглядит так:

  1. Узнать текущую версию ядра: uname -r
  2. Проверить наличие модуля: lsmod | grep module_name
  3. Посмотреть сведения о модуле: modinfo module_name
  4. Проверить логи: dmesg | tail -n 100
  5. Сверить наличие headers под текущее ядро

Если ошибка появилась сразу после обновления ядра, первым подозреваемым должен быть внешний out-of-tree драйвер, который не пересобрался автоматически.

Проблемы с VirtualBox (vboxdrv)

Сообщение virtualbox linux kernel driver not installed — одна из самых типичных ошибок на Linux-десктопах. Причина почти всегда в том, что модуль vboxdrv отсутствует, не собран или не загружается после смены ядра.

Проверьте сначала базовые вещи:

  • установлены ли headers для текущего kernel;
  • установлены ли пакеты сборки;
  • не менялось ли ядро после последнего обновления VirtualBox;
  • есть ли DKMS и успешно ли он пересобрал модуль.

Типовой набор действий:

uname -r
lsmod | grep vbox
sudo modprobe vboxdrv
sudo /sbin/vboxconfig

Если vboxconfig падает с ошибкой сборки, почти наверняка проблема в headers, compiler mismatch или Secure Boot/подписи модуля. На системах с включённым Secure Boot неподписанный модуль может собраться, но не загрузиться.

Общие причины и диагностика

Вот основные причины, из-за которых драйверы и модули не работают:

  • несовместимость версии ядра и модуля;
  • неустановленные или неподходящие kernel headers;
  • отсутствующие зависимости;
  • blacklist модуля в конфигурации;
  • конфликт двух драйверов для одного устройства;
  • отсутствующая firmware;
  • проблемы подписи модуля при Secure Boot.
Как проверить, какой драйвер используется

  • для PCI-устройств: lspci -k;
  • для USB-устройств: lsusb и логи dmesg;
  • для загруженных модулей: lsmod;
  • для сведений о модуле: modinfo.
Риски и ограничения

  • ручная загрузка через insmod удобна для теста, но хуже подходит для штатного сопровождения;
  • после обновления kernel внешний драйвер может перестать работать до пересборки;
  • выгрузка “живого” драйвера может обрушить доступ к устройству;
  • на production-серверах ручные эксперименты с модулями лучше делать только с консольным доступом и планом отката.

В 80% случаев проблема находится не по “переустановке Linux”, а по цепочке uname -r → headers → modprobe → dmesg.


Linux Kernel Headers: что это и как установить

Что такое headers

Kernel headers — это набор заголовочных файлов и служебных файлов сборки, которые нужны для компиляции внешних модулей и некоторых низкоуровневых программ. Это не “полное исходное дерево ядра”, но именно они дают компилятору описания структур, API и конфигурации, с которыми должен совпадать модуль.

Зачем они нужны

Без headers система может прекрасно работать, пока вы не попытаетесь собрать внешний модуль. Именно поэтому обычный пользователь может долго о них не знать, а потом внезапно столкнуться с ошибкой во время установки VirtualBox, NVIDIA, WireGuard из нестандартного источника или собственного driver module.

Headers нужны для:

  • сборки внешних kernel modules;
  • пересборки DKMS-пакетов после обновления ядра;
  • компиляции некоторых драйверов и низкоуровневых компонентов;
  • разработки и тестирования модулей.

Установка headers

Команда зависит от дистрибутива, но суть одна: ставить нужно пакет под текущую версию запущенного ядра, а не абстрактно “самые новые headers”.

# Ubuntu / Debian
sudo apt install linux-headers-$(uname -r)

# Arch Linux
sudo pacman -S linux-headers

# Fedora
sudo dnf install kernel-headers kernel-devel

После установки полезно проверить, существует ли каталог сборки:

ls -l /lib/modules/$(uname -r)/build

Если путь отсутствует или указывает не туда, сборка внешнего модуля почти наверняка завершится ошибкой.

ДистрибутивЧто ставитьНа что обратить внимание
Ubuntu / Debianlinux-headers-$(uname -r)Важно точное совпадение версии
Archlinux-headersДля альтернативных ядер нужен свой пакет
Fedorakernel-headers и kernel-develДля внешней сборки часто нужен именно kernel-devel
Практические сценарии выбора

  • если нужен только запуск Linux — headers обычно не нужны;
  • если ставите VirtualBox или внешний драйвер — ставьте headers сразу;
  • если ядро обновляется часто — лучше использовать DKMS, чтобы не пересобирать модуль вручную после каждого апдейта;
  • если включён Secure Boot — заранее учитывайте вопрос подписи модуля, иначе сборка может пройти, а загрузка нет.

FAQ

Где хранятся kernel modules?

Обычно в /lib/modules/$(uname -r)/. Внутри лежат сами .ko-файлы, карты зависимостей и каталоги по подсистемам.

Как автоматически загружать модуль при старте?

Добавьте имя модуля в файл внутри /etc/modules-load.d/ или используйте механизм пакета/дистрибутива, если модуль ставится официальным способом.

Что делать при конфликте драйверов?

Сначала выяснить, какой модуль реально привязан к устройству, через lspci -k или modinfo. После этого уже смотреть blacklist, приоритеты загрузки и firmware. Удалять “лишний” драйвер вслепую — плохая идея.

Что такое DKMS и зачем он нужен?

DKMS — это механизм автоматической пересборки внешних модулей под новое ядро. Он особенно полезен там, где модуль не входит в основное дерево kernel и должен переживать обновления системы.

Что такое kernel signing?

Это подпись модуля, которую может требовать система, особенно при включённом Secure Boot. Без корректной подписи модуль иногда собирается нормально, но ядро отказывается его загружать.

Что лучше использовать: insmod или modprobe?

Для повседневной работы — modprobe. Для ручного теста своего конкретного .koinsmod.


Итоги

Если убрать лишнюю терминологию, картина простая: драйвер — это логика работы с устройством, модуль — это удобный способ доставить эту логику в ядро, а headers — техническая база для сборки внешнего кода под конкретный kernel.

Когда что-то не работает, не нужно метаться между форумами. Гораздо полезнее идти по короткой цепочке: проверить версию ядра, наличие headers, статус модуля через lsmod/modprobe и посмотреть реальную причину в dmesg. Именно так решается большинство проблем — от собственного kernel module до ошибки VirtualBox с vboxdrv.

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x