Перейти к содержанию

Ядро Linux

Это сердце ОС. Первоначальный выпуск 0.01 был выпущен 17 сентября 1991 года. Самый крупный проект с открытым исходным кодом в мире. Написан на C с расширениями GCC и ASM (AT&T). Скомпилированное ядро - файл vmlinux (в формате объектного файла ELF, COFF или a.out)

Ядро имеет монолитную архитектуру с загружаемыми во время выполнения модулями (modular monolithic). Все части ядра находятся в одном адресном пространстве. Все драйверы устройств работают в пространстве ядра.

Требования ядра:

  • ЦП с MMU (блок управления памятью)
  • Достаточный ОЗУ (2 мб+);
  • Минимальные возможности ввода-вывода со средствами отладки (например, последовательный порт)
  • Ядро должно иметь возможность загружать корневую файловую систему из какого-либо постоянного хранилища или получать к ней доступ по сети

Ядро и его исходники здесь: kernel.org

Хорошая статья на тему сборки linux.

Конфигурация ядра в файле .config. Для генерации файла требуется скачать исходники и выполнить make config. Если конфигурация уже была (например, вы ранее строили ОС и нужно обновить) можно использовать make oldconfig для интерактивного обновления файла конфигурации или make olddefconfig для автоматического применения "дефолтных" значений ко всем новым полям.

Также существуют графические варианты кофигурации:

  • make menuconfig - псевдографическийинтерфейс в консоли.
  • make xconfig (for Qt), make gconfig (for GTK) - графическое окно.

В готовой конфигурации можно переключать опции двумя способами:

  • scripts/config, например: scripts/config --disable SYSTEM_TRUSTED_KEYS - рекомендованый способ. Есть множество ключей.
  • sed, например: sed -i 's/^CONFIG_TC=y/# CONFIG_TC is not set/' .config

Для реализации меню, инструкций и конфигурации используется Kconfig.

Текущая конфигурация ядра может быть найдена тут:

/proc/config.gz
/boot/config
/boot/config-$(uname -r)

Что находится в .config

CONFIG_RUNTIME_TESTING_MENU=y – опция выбрана
# CONFIG_TEST_USER_COPY is not set  – опция не выбрана
CONFIG_TEST_BPF=m – опция выбрана и добавляется в  виде модуля ядра

Выполнение задания

Собрать новое ядро с rt-patch, установить и запустить операционную систему с новым ядром Linux с наложенным rt-patch Сравните результаты работы теста cycletest для обычного ядра и ядра с rt-patch

C версии 6.12 патч rt-patch не требуется, достаточно включить PREEMPT_RT.

Ядро собирается на самой ОС, запуск и отладка - в QEMU (может потребоваться доустановить sudo apt install qemu-system-x86).

Пример с патчем приведен для v6.6.127 (longterm).

Выполняем скачивание исходников (включая rt-tests для cyclictest) (busybox сразу распаковываем):

mkdir build
KERNEL_VERSION=v6.6.127
git clone --branch $KERNEL_VERSION --depth 1 https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git build/linux-$KERNEL_VERSION
BUSYBOX_VER="1.37.0"
wget -q https://busybox.net/downloads/busybox-$BUSYBOX_VER.tar.bz2

mkdir -p build/busybox-$BUSYBOX_VER
tar xjf busybox-$BUSYBOX_VER.tar.bz2 -C build/

cd build
git clone https://git.kernel.org/pub/scm/utils/rt-tests/rt-tests.git

Собираем все из исходников. В первую очередь - busybox:

cd busybox-1.37.0
make defconfig
make -j$(nproc) CONFIG_STATIC=y
file busybox
make CONFIG_STATIC=y CONFIG_PREFIX=../rootfs install
cd ..

Создаем файловую структуру будущей ОС и init script:

mkdir -p rootfs/{bin,sbin,etc,proc,sys,dev,run,tmp,var}
mkdir -p rootfs/usr/{bin,sbin}

cat > rootfs/init << 'EOF'
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t tmpfs tmpfs /run
mount -t tmpfs tmpfs /tmp
mkdir -p /dev/shm
mount -t tmpfs shm /dev/shm
mdev -s

if [ -c /dev/fb0 ]; then
  TTY=/dev/tty1
else
  TTY=/dev/ttyS0
fi

# Очистка и приветсвие
echo 0 > /proc/sys/kernel/printk
printf "\033c" > $TTY
cat << INNER > $TTY
===============================
   Minimal Linux by Vlad Ryabchevsky
   Kernel: $(uname -r)
   Time: $(date)
===============================
INNER

# Запускаем shell
exec setsid sh -c "exec sh <'$TTY' >'$TTY' 2>'$TTY'"
EOF

chmod +x rootfs/init

Сбока и копирование cyclictest

cd rt-tests
make clean
make CFLAGS="-static -O2 -D_GNU_SOURCE" LDFLAGS="-static -lnuma -lpthread -lrt" cyclictest
cp cyclictest ../rootfs/usr/bin/
chmod +x ../rootfs/usr/bin/cyclictest
cd ..

Нужно больше приложений? Не вопрос! - качайте их исходники и собирайте. С другой стороны, не проще ли тогда взять тот же ubuntu?

Теперь создается rootfs-образ:

cd rootfs
find . | cpio -o -H newc | gzip > ../rootfs.cpio.gz
cd ..

Дальше - сборка ядра linux:

cd linux-$KERNEL_VERSION
make tinyconfig

./scripts/config \
  -e 64BIT \
  -e PCI \
  -e PCI_HOST_GENERIC \
  -e TTY \
  -e BLK_DEV_INITRD \
  -e SERIAL_8250 \
  -e SERIAL_8250_CONSOLE \
  -e BINFMT_ELF \
  -e BINFMT_MISC \
  -e BINFMT_SCRIPT \
  -e DEVTMPFS \
  -e DEVTMPFS_MOUNT \
  -e TMPFS \
  -e PRINTK \
  -e EARLY_PRINTK \
  -e PROC_FS \
  -e SYSFS \
  --set-str INITRAMFS_SOURCE "../rootfs.cpio.gz" \
  -e RD_GZIP \
  -e INITRAMFS_COMPRESSION_GZIP \
  -e EFI \
  -e EFI_STUB \
  -e FB \
  -e FB_EFI \
  -e FRAMEBUFFER_CONSOLE

make olddefconfig
make -j$(nproc)
ls -lh arch/x86/boot/bzImage

Если небыло ошибок, то запускаем ВМ:

qemu-system-x86_64 -m 2G     -kernel linux-$KERNEL_VERSION/arch/x86/boot/bzImage     -initrd rootfs.cpio.gz     -machine pc     -cpu qemu64     -append "console=ttyS0 init=/bin/busybox" -nographic
cyclictest -t 1 -i 200 -l 1000 -p 80

Результат БЕЗ патча:

~ # cyclictest -t 1 -i 200 -l 1000 -p 80
WARN: stat /dev/cpu_dma_latency failed: No such file or directory
WARN: High resolution timers not available
policy: fifo: loadavg: 0.00 0.00 0.00 1/17 28

T: 0 (   28) P:80 I:200 C:   1000 Min:   2592 Act: 3819 Avg: 3852 Max:    4289

Далее, скачиваем необходимый rt-patch

wget  https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/patch-6.6.127-rt69.patch.xz
xz -dk patch-6.6.127-rt69.patch.xz
cd linux-$KERNEL_VERSION
make clean
patch -p1 < ../patch-6.6.127-rt69.patch

Возвращаемся к шагу конфигурирования ядра, перед сборкой открываем make menuconfig и включаем General setup -> Preemption Model -> Fully Preemptible Kernel

Аналогично запускаем и видим:

~ # cyclictest -t 1 -i 200 -l 1000 -p 80
WARN: stat /dev/cpu_dma_latency failed: No such file or directory
WARN: High resolution timers not available
policy: fifo: loadavg: 0.32 0.07 0.02 1/30 41

T: 0 (   41) P:80 I:200 C:    999 Min:   3288 Act: 3955 Avg: 3919 Max:    7292