Настройка окружения для тестирования изменений в ядре Linux

image

Иногда (редко, но все-же) возникает потребность что-то дописать или переделать в ядре всеми нами любимого линукса. И тогда возникает вопрос: А как все эти изменения запустить и проверить быстро и без перекуров?

Одно дело, если мы можем организовать нашу новую функциональность в виде модуля, тогда нам довольно просто можно тестировать его без перезагрузки самого ядра, простым включением и выключением через insmod. Но что делать, если концепция модульности неприменима? Например, как в моем случае, когда потребовалось добавить новую подсистему контрольных групп (cgroups) для Jet9 и нужно было перезапускать ядро каждый раз, чтобы проверить внесенные изменения?
В этом нам поможет система виртуализации qemu (или qemu-kvm), т.к. она умеет принимать в качестве параметров не только раздел с системой, но и сам файл с ядром (bzImage) и initramfs. Используя данную функциональность мы можем быстро настроить и использовать тестовое окружение. Настройка состоит всего из двух шагов:

  • Создание initramfs
  • Запуск qemu-kvm с новым ядром и созданным initramfs

Далее я кратко опишу эти два шага, а на все доп. вопросы отвечу в комментариях.

Создание initramfs

Создадим структуру каталогов:

mkdir -p initramfs/{bin,sbin,etc,proc,sys,cgroup,usr/bin,usr/sbin}

Добавим все необходимые unix-утилиты. Для этого проще всего использовать busybox. Бинарник можно скачать отсюда и положить в /bin/busybox. Обязательно надо добавить симлинк для sh, чтобы запустился init:

cd initramfs
ln -s bin/busybox bin/sh

Добавим следующий скрипт в ./init (он должен находиться в корне нашего образа):

#!/bin/sh

#Create unix-utils symlinks to /bin/busybox
/bin/busybox --install -s

#Mount pseudo-fs
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t cgroup cgroup /cgroup

#Create null device 
mknod /dev/null c 1 3

exec sh


Он при запуске создаст симлинки на все основные unix-утилиты, примонтирует удобные для нас pseudo-fs, создаст устройство /dev/null (чтобы его можно было потом использовать в своих скриптах и подавлять ненужный вывод) и запустит шелл.

Конечно, если вам нужно что-то сверх этого, вы можете легко изменить этот скрипт по своему усмотрению. Я, например, в него перед запуском шелла добавил запуск тестов, чтобы каждый раз вручную их не запускать. Точно так же можно поступить и с дополнительными утилитами — просто добавьте их в образ по тем путям, которые вам нужны. Аналогично с модулями — если вы их используете при тестировании, просто добавьте их в /lib/modules/

Далее, запакуем все в один файл:

find . | cpio -H newc -o | gzip -c > ../initramfs.gz

Все, initramfs готов.

Запуск kvm

Тут все довольно просто, все запускается командой:

kvm -m 128 -kernel ./arch/x86/boot/bzImage -initrd initramfs.igz -serial stdio -append "console=ttyAMA0 console=ttyS0" -display none


параметры:
-m — сколько оперативки выделяем на машину
-kernel — новоскомпилированное ядро
-initrd — созданный выше initramfs
-append — параметры ядру

самое интересное — это параметр -append, в нем мы перенаправляем ввод/вывод в serial port (помните такой? ;), а параметром -serial перенаправляем последовательный порт в stdin/stdout. Это позволит нам получить вывод ядра прямо в консоль, минуя черное окошко 80×25, в котором не радует решительно все. Кстати, параметр -display none позволяет убрать и его, чтобы не отсвечивало (нам же ядро интересно, а не gui).

Profit! Теперь ядро загружается и готово к проверке меньше чем за 3 секунды.

© Habrahabr.ru