Ubuntu 커널 빌드를 하려면 Host PC에 커널 빌드에 필요한 패키지들을 설치하고, Kernel 소스를 준비 후 빌드하고 부트로더(Grub)에 반영해야 한다. 이 글을 우분투 환경에서 커널을 빌드하고, 적용하는 방법을 설명한다.
빌드 환경 셋업
우선 커널 빌드는 로컬에서 빌드해서 확인한 결과 소스를 포함해서 대략 20G정도가 사용된다. 커널 빌드를 시작하기에 앞서 충분한 용량을 확보하고 시작하는 것이 좋다.
시스템에 커널을 구축하기 위해 필요한 몇 가지 도구들이 있다. 이러한 패키지들을 설치한 적이 없다면 다음의 패키지들을 설치한다.
sudo apt install build-essential libncurses-dev gawk flex bison openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf llvm
git을 설치한다.
sudo apt install git
우분투 커널 소스 얻기
우분투 커널 소스를 얻으려면 linux-source 패키지를 받는다.
sudo apt install linux-source
linux-source가 다운 됐는지 /usr/src 에서 소스를 확인한다.
$ ls -la
total 20
drwxr-xr-x 5 root root 4096 Aug 25 15:35 .
drwxr-xr-x 14 root root 4096 Aug 10 00:17 ..
drwxr-xr-x 25 root root 4096 Aug 25 15:22 linux-headers-5.15.0-79
drwxr-xr-x 7 root root 4096 Aug 25 15:22 linux-headers-5.15.0-79-generic
drwxr-xr-x 4 root root 4096 Aug 25 15:35 linux-source-5.15.0
lrwxrwxrwx 1 root root 47 Jul 10 13:33 linux-source-5.15.0.tar.bz2 -> linux-source-5.15.0/linux-source-5.15.0.tar.bz2
또는, git 으로 관리되고 있는 우분투 커널 소스를 받으려면 아래와 같이 git clone 하여 받는다.
git clone git://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/jammy
config 설정
다운 받은 커널 소스로 이동해서, 현재 커널의 config를 다운받은 커널 소스에 .config 이름으로 복사한다.
cp /boot/config-$(uname -r) .config
동일한 config를 적용하려면 아래와 같이 oldconfig가 적용되게 한다. 이러면 복사한 .config가 그대로 적용된다.
$ make oldconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
HOSTCC scripts/kconfig/confdata.o
HOSTCC scripts/kconfig/expr.o
LEX scripts/kconfig/lexer.lex.c
YACC scripts/kconfig/parser.tab.[ch]
HOSTCC scripts/kconfig/lexer.lex.o
HOSTCC scripts/kconfig/menu.o
HOSTCC scripts/kconfig/parser.tab.o
HOSTCC scripts/kconfig/preprocess.o
HOSTCC scripts/kconfig/symbol.o
HOSTCC scripts/kconfig/util.o
HOSTLD scripts/kconfig/conf
#
# configuration written to .config
#
추가적으로, 변경하려는 config가 있으면 menuconfig를 하여 필요한 config를 추가/제거 한다.
make menuconfig
커널 빌드
커널 빌드를 들어가기에 앞서, 로컬 빌드임을 표기하기 위해 Makefile 에서 EXTRAVERSION
을 수정한다. 아래는 로컬빌드임을 나타내기 위해 “-local”을 입력했는데, 이 경우 install 시에 버전을 5-15-111-local 로 표기하게 된다.
# SPDX-License-Identifier: GPL-2.0
VERSION = 5
PATCHLEVEL = 15
SUBLEVEL = 111
EXTRAVERSION = -local # <-- 수정
NAME = Trick or Treat
일단 커널 소스 디렉토리를 정리하고 커널 및 모듈을 컴파일한다.
make clean
make
컴파일 도중 아래와 같이 debian/canonical-certs.pem
에러가 발생하는 경우에는, SYSTEM_TRUSTED_KEYS
를 disable 하거나 해준후 make를 다시 진행하거나, 다운받은 커널 소스에 있는 debian/canonical-certs.pem을 copy 하여 진행할 수 있다.
make[1]: *** No rule to make target 'debian/canonical-certs.pem', needed by 'certs/x509_certificate_list'. Stop.
make: *** [Makefile:1900: certs] Error 2
./scripts/config --disable SYSTEM_TRUSTED_KEYS
make
or
cp -a /usr/src/linux-source-5.15.0/debian .
make
만약 아래와 같이 debian/canonical-revoked-certs.pem
에러가 발생하면, 위에 SYSTEM_TRUSTED_KEYS
를 disable 한 경우이므로, 아래와 같이 SYSTEM_REVOCATION_KEYS
를 disable 해준 후 make를 다시 진행한다.
make[1]: *** No rule to make target 'debian/canonical-revoked-certs.pem', needed by 'certs/x509_revocation_list'. Stop.
make: *** [Makefile:1900: certs] Error 2
./scripts/config --disable SYSTEM_REVOCATION_KEYS
make
필자의 경우 커널 컴파일 중 거의 끝무렵에 아래와 같이 BTF 관련 에러가 발생했다.
CC arch/x86/lib/iomem.o
AS arch/x86/lib/iomap_copy_64.o
AR arch/x86/lib/built-in.a
GEN .version
CHK include/generated/compile.h
LD vmlinux.o
MODPOST vmlinux.symvers
WARNING: modpost: vmlinux.o(.text+0x9f91f7): Section mismatch in reference from the function i8042_probe() to the variable .init.rodata:i8042_quirks
The function i8042_probe() references
the variable __initconst i8042_quirks.
This is often because i8042_probe lacks a __initconst
annotation or the annotation of i8042_quirks is wrong.
MODINFO modules.builtin.modinfo
GEN modules.builtin
BTF: .tmp_vmlinux.btf: pahole (pahole) is not available
Failed to generate BTF for vmlinux
Try to disable CONFIG_DEBUG_INFO_BTF
make: *** [Makefile:1230: vmlinux] Error 1
이를 방지하기 위해 미리 CONFIG_DEBUG_INFO_BTF 을 disable 하고 빌드를 시작하거나, dwarves 패키지를 설치후에 다시 make 한다.
./scripts/config --disable DEBUG_INFO_BTF
make
or
sudo apt install dwarves
make
모듈 설치(modules_install)
컴파일이 완료되면 커널 모듈(modules) ko 이미지들을 install 한다. /lib/modules 에 install 되기 때문에 sudo 로 실행한다.
$ sudo make modules_install
INSTALL arch/x86/crypto/aegis128-aesni.ko
INSTALL arch/x86/crypto/aesni-intel.ko
INSTALL arch/x86/crypto/blowfish-x86_64.ko
INSTALL arch/x86/crypto/camellia-aesni-avx-x86_64.ko
...
INSTALL sound/x86/snd-hdmi-lpe-audio.ko
INSTALL sound/xen/snd_xen_front.ko
INSTALL ubuntu/xr-usb-serial/xr_usb_serial_common.ko
DEPMOD 5.4.111-local
install 이 제대로 되었는지 /lib/modules 를 확인한다.
$ ls /lib/modules/5.4.111-local
build modules.alias modules.builtin modules.builtin.bin modules.dep modules.devname modules.softdep modules.symbols.bin
kernel modules.alias.bin modules.builtin.alias.bin modules.builtin.modinfo modules.dep.bin modules.order modules.symbols source
커널 설치(install)
커널을 install 한다.
sudo make install
arch/x86/Makefile:142: CONFIG_X86_X32 enabled but no binutils support
sh ./arch/x86/boot/install.sh 5.15.111-local \
arch/x86/boot/bzImage System.map "/boot"
run-parts: executing /etc/kernel/postinst.d/dkms 5.15.111-local /boot/vmlinuz-5.15.111-local
* dkms: running auto installation service for kernel 5.15.111-local [ OK ]
run-parts: executing /etc/kernel/postinst.d/initramfs-tools 5.15.111-local /boot/vmlinuz-5.15.111-local
update-initramfs: Generating /boot/initrd.img-5.15.111-local
run-parts: executing /etc/kernel/postinst.d/unattended-upgrades 5.15.111-local /boot/vmlinuz-5.15.111-local
run-parts: executing /etc/kernel/postinst.d/update-notifier 5.15.111-local /boot/vmlinuz-5.15.111-local
run-parts: executing /etc/kernel/postinst.d/xx-update-initrd-links 5.15.111-local /boot/vmlinuz-5.15.111-local
I: /boot/initrd.img is now a symlink to initrd.img-5.15.111-local
run-parts: executing /etc/kernel/postinst.d/zz-update-grub 5.15.111-local /boot/vmlinuz-5.15.111-local
Sourcing file `/etc/default/grub'
Sourcing file `/etc/default/grub.d/init-select.cfg'
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-5.15.111-local
Found initrd image: /boot/initrd.img-5.15.111-local
Found linux image: /boot/vmlinuz-5.15.0-79-generic
Found initrd image: /boot/initrd.img-5.15.0-79-generic
Warning: os-prober will not be executed to detect other bootable partitions.
Systems on them will not be added to the GRUB boot configuration.
Check GRUB_DISABLE_OS_PROBER documentation entry.
done
커널 instalL이 제대로 되었는지 /boot 를 확인한다. 아래와 같이 vmlinuz-5.4.111-local, initrd.img-5.4.111-local 이 있는지 확인하고, 각각 vmlinz, initrd.img 링크가 잘 되어 있는지 확인한다.
$ ls -l /boot/
total 899056
-rw-r--r-- 1 root root 261881 Jul 10 13:33 config-5.15.0-79-generic
-rw-r--r-- 1 root root 261629 Aug 26 07:53 config-5.15.111-local
drwxr-xr-x 5 root root 4096 Aug 26 07:54 grub
lrwxrwxrwx 1 root root 25 Aug 26 07:54 initrd.img -> initrd.img-5.15.111-local
-rw-r--r-- 1 root root 110809304 Aug 26 01:17 initrd.img-5.15.0-79-generic
-rw-r--r-- 1 root root 775144226 Aug 26 07:54 initrd.img-5.15.111-local
lrwxrwxrwx 1 root root 28 Aug 26 01:17 initrd.img.old -> initrd.img-5.15.0-79-generic
-rw------- 1 root root 6271933 Jul 10 13:33 System.map-5.15.0-79-generic
-rw-r--r-- 1 root root 6091626 Aug 26 07:53 System.map-5.15.111-local
lrwxrwxrwx 1 root root 22 Aug 26 07:53 vmlinuz -> vmlinuz-5.15.111-local
-rw------- 1 root root 11613672 Jul 10 15:22 vmlinuz-5.15.0-79-generic
-rw-r--r-- 1 root root 10151232 Aug 26 07:53 vmlinuz-5.15.111-local
lrwxrwxrwx 1 root root 25 Aug 26 01:17 vmlinuz.old -> vmlinuz-5.15.0-79-generic
시스템 재시작 및 확인
시스템을 재시작하여 새로 설치된 커널 부팅을 확인한다.
sudo reboot
$ uname -r
5.15.111-local