Инженеру рано или поздно приходится не просто пользоваться готовым ядром, а понимать, из чего оно собрано: почему система грузится с диска, который сам по себе требует драйвер для чтения, какой именно образ ядра лежит в /boot, чем модуль .ko отличается от вкомпилированного драйвера и зачем между загрузчиком и реальным корнем стоит временная файловая система initramfs. В этом уроке мы разбираем карту компонентов ядра, учимся читать версию и именование, находить и считать модули, и понимать роль initramfs - фундамент перед сборкой и тюнингом ядра в следующих уроках.

Как это работает
Ядро Linux - это один большой бинарный файл плюс набор подгружаемых модулей. Образ ядра живет в /boot. На x86 это обычно vmlinuz - сжатый, готовый к загрузке образ. Историческое имя bzImage (big zImage) - это формат, в который собирается сжатое ядро для x86; vmlinuz в /boot чаще всего и есть переименованный bzImage. Не путай с vmlinux - это несжатый ELF-образ из дерева сборки, его используют для отладки, а не для загрузки.
Драйверы и подсистемы делятся на две категории. То, что нужно ядру сразу при старте - драйвер контроллера диска, файловая система корня, базовый ввод-вывод - либо вкомпилировано прямо в монолитный образ (опция Y в конфиге), либо лежит в initramfs. Все остальное выносится в модули (опция M) - отдельные файлы .ko (kernel object) в /lib/modules/$(uname -r)/. Модуль грузится по требованию: воткнул USB-токен, udev определил устройство и через modprobe подтянул нужный .ko. Это экономит память и делает ядро гибким: один образ обслуживает тысячи разных конфигураций железа.
Теперь ключевой парадокс загрузки. Чтобы прочитать корневую ФС, ядру нужен драйвер этой ФС и драйвер контроллера диска. Но эти драйверы - модули, которые лежат на той самой корневой ФС, которую еще нельзя прочитать. Курица и яйцо. Решение - initramfs (initial RAM filesystem): маленький архив (cpio, сжатый gzip/zstd), который загрузчик кладет в память рядом с ядром. Ядро распаковывает его в tmpfs, запускает оттуда минимальный init (в современных дистрибутивах это скрипты dracut или initramfs-tools плюс часто systemd), который грузит нужные модули, при необходимости собирает LVM/RAID, расшифровывает LUKS, находит настоящий корень, делает switch_root на него и передает управление штатному /sbin/init. Старое слово initrd означает почти то же, но технически это образ блочного устройства (ramdisk), а не cpio-архив; в 2026 везде используется именно initramfs, хотя файл по традиции может называться initrd.img.
Версия ядра кодируется как ГЛАВНАЯ.ВТОРАЯ.ИСПРАВЛЕНИЕ, например 6.12.0. После номера дистрибутивы добавляют свой суффикс - локальную версию и тип сборки, например 6.12.0-12-generic в Ubuntu или 6.12.0-55.el10.x86_64 в RHEL 10. Эта полная строка - и есть имя каталога в /lib/modules, поэтому модули жестко привязаны к конкретной сборке ядра: пересобрал ядро - пересобери и установи модули.
Команды и примеры
Версия работающего ядра и где что лежит.
Код: Выделить всё
uname -r # только релиз ядра, напр. 6.12.0-12-generic
uname -a # все: ядро, хост, архитектура, дата сборки
cat /proc/version # версия + компилятор и время сборки ядра
cat /proc/cmdline # с какими параметрами загрузчик запустил ядро
ls /boot/ # vmlinuz-*, initrd.img-*/initramfs-*, config-*, System.map-*
ls /lib/modules/$(uname -r)/ # дерево модулей текущего ядра
Код: Выделить всё
zcat /proc/config.gz | grep -i ext4 # как собран драйвер ext4
# вывод CONFIG_EXT4_FS=y -> вкомпилирован; =m -> модуль; нет строки -> выключен
grep CONFIG_EXT4_FS /boot/config-$(uname -r)
Код: Выделить всё
lsmod # загруженные модули, их размер и кто их использует
modinfo ext4 # метаданные .ko: путь, зависимости, параметры, alias
find /lib/modules/$(uname -r) -name '*.ko*' | wc -l # сколько модулей собрано
Код: Выделить всё
# Debian 13 / Ubuntu 24.04 - инструменты initramfs-tools
lsinitramfs /boot/initrd.img-$(uname -r) | grep -i nvme
# RHEL 10 / Fedora 41+ - dracut
lsinitrd /boot/initramfs-$(uname -r).img | grep -i nvme
Код: Выделить всё
update-initramfs -u -k all # Debian/Ubuntu
dracut -f # RHEL/Fedora, пересобрать для текущего ядра
- Путаница vmlinuz / vmlinux / bzImage. Грузится сжатый vmlinuz (он же bzImage на x86). vmlinux - несжатый ELF только для отладки, в /boot его обычно нет.
- Драйвер диска или ФС собран как модуль, но не включен в initramfs. Результат - "VFS: Unable to mount root fs", kernel panic при загрузке. Лечится добавлением модуля в конфиг initramfs и пересборкой.
- Модули от чужой версии ядра. /lib/modules/X не совпадает с uname -r - modprobe не найдет .ko. После ручной сборки ядра нельзя забывать make modules_install.
- initrd против initramfs в терминологии. На современных системах это всегда cpio-initramfs, даже если файл называется initrd.img. Старый ramdisk-initrd в 2026 не используется.
- Удалили старое ядро, но его каталог в /lib/modules остался (или наоборот). Рассинхрон ломает сборку DKMS-модулей и пересборку initramfs.
- Считать, что /proc/config.gz есть всегда. Он появляется только если ядро собрано с CONFIG_IKCONFIG_PROC; иначе смотри /boot/config-$(uname -r).
- Выведи точную версию своего ядра тремя способами: uname -r, cat /proc/version, ls /boot. Сравни строки и найди суффикс дистрибутива.
- Посчитай, сколько всего модулей .ko собрано для твоего ядра и сколько из них сейчас загружено (find и lsmod). Объясни разницу.
- Через modinfo посмотри метаданные модуля файловой системы (ext4 или xfs): путь к файлу, его зависимости (depends) и алиасы.
- Определи, как в твоем ядре собран драйвер корневой ФС: вкомпилирован (=y) или модуль (=m). Используй /proc/config.gz или /boot/config-*.
- Распакуй список содержимого своего initramfs (lsinitramfs или lsinitrd) и найди в нем модуль контроллера диска (nvme, ahci или virtio_blk).
- Посмотри /proc/cmdline и найди параметр root= - на каком устройстве система ищет корень.
- Чем отличаются файлы vmlinuz, vmlinux и bzImage и какой из них реально загружается?
- Зачем нужен initramfs и какую проблему загрузки он решает? Чем он отличается от классического initrd?
- Где физически лежат модули ядра и почему они привязаны к конкретной версии ядра?
- Как по конфигу определить, что подсистема вкомпилирована в ядро, вынесена в модуль или отключена?
- Какой командой посмотреть зависимости и параметры конкретного модуля, не загружая его?
- Чем отличаются update-initramfs и dracut и в каких дистрибутивах применяется каждый?