Ubuntu 커널 빌드

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

참고

답글 남기기