Denna korta instruktion visar hur man kan bygga en minimal Linuxkärna med ett minimalt initramfs-root-filsystem och prova dem i Qemu. Vi tittar på två alternativ för initramfs-root-filsystemet:
- att utgå från Busybox-källkoden (inspirerad av Mitchel Humpherys),
- med hjälp av Buildroot.
Vi visar också hur man kan kompilera och testa ett användarprogram, Hello_world och en inläsningsbar kärnmodul, Hello_world.
export OPT=/opt
export BUILDS=/some/where/mini_linux
mkdir -p $BUILDS
Kommentar: $OPT/linux är där du extraherar källkoden för kärnan.
export LINUX=$OPT/linux (här extraherar du koden för kärnan)
export LINUX_BUILD=$BUILDS/linux
mkdir -p $LINUX_BUILD
cd $LINUX
make O=$LINUX_BUILD allnoconfig
cd $LINUX_BUILD
make menuconfig
Konfigurera kärnan:
64-bit kernel ---> yes
General setup ---> Initial RAM filesystem and RAM disk (initramfs/initrd) support ---> yes
General setup ---> Configure standard kernel features ---> Enable support for printk ---> yes
Executable file formats / Emulations ---> Kernel support for ELF binaries ---> yes
Executable file formats / Emulations ---> Kernel support for scripts starting with #! ---> yes
Device Drivers ---> Generic Driver Options ---> Maintain a devtmpfs filesystem to mount at /dev ---> yes
Device Drivers ---> Generic Driver Options ---> Automount devtmpfs at /dev, after the kernel mounted the rootfs ---> yes
Device Drivers ---> Character devices ---> Enable TTY ---> yes
Device Drivers ---> Character devices ---> Serial drivers ---> 8250/16550 and compatible serial support ---> yes
Device Drivers ---> Character devices ---> Serial drivers ---> Console on 8250/16550 and compatible serial port ---> yes
File systems ---> Pseudo filesystems ---> /proc file system support ---> yes
File systems ---> Pseudo filesystems ---> sysfs file system support ---> yes
Bygg kärnan:
time make -j8
...
Kernel: arch/x86/boot/bzImage is ready (#1)
real 2m37.247s
user 1m58.541s
sys 0m25.542s
Kommentar: $OPT/busybox är där du extraherar källkoden för Busybox.
export BUSYBOX=$OPT/busybox _här ska källkoden för Busybox vara_
export BUSYBOX_BUILD=$BUILDS/busybox
mkdir -p $BUSYBOX_BUILD
cd $BUSYBOX
make O=$BUSYBOX_BUILD defconfig
cd $BUSYBOX_BUILD
make menuconfig
Konfigurera Busybox:
Busybox Settings ---> Build Options ---> Build BusyBox as a static binary (no shared libs) ---> yes
Bygg Busybox:
time make -j8
...
Final link with: m
real 0m20.356s
user 0m46.959s
sys 0m10.628s
Installera Busybox:
make install
Skapa initramfs:
export INITRAMFS_BUILD=$BUILDS/initramfs
mkdir -p $INITRAMFS_BUILD
cd $INITRAMFS_BUILD
mkdir -p bin sbin etc proc sys usr/bin usr/sbin
cp -a $BUSYBOX_BUILD/_install/* .
Lägg till ett skript,$INITRAMFS_BUILD/init
till initramfs, och låt innehållet vara följande:
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
cat <<!
Boot took $(cut -d' ' -f1 /proc/uptime) seconds
_ _ __ _
/\/\ (_)_ __ (_) / /(_)_ __ _ ___ __
/ \| | '_ \| | / / | | '_ \| | | \ \/ /
/ /\/\ \ | | | | | / /__| | | | | |_| |> <
\/ \/_|_| |_|_| \____/_|_| |_|\__,_/_/\_\
Welcome to mini_linux
!
exec /bin/sh
Skapa arkivet initramfs:
chmod +x init
find . -print0 | cpio --null -ov --format=newc \
| gzip -9 > $BUILDS/initramfs.cpio.gz
qemu-system-x86_64 -kernel $LINUX_BUILD/arch/x86_64/boot/bzImage \
-initrd $BUILDS/initramfs.cpio.gz -nographic \
-append "console=ttyS0"
Kommentar: för bättre prestanda, lägg till flaggan-enable-kvm
om din värd har KVM aktiverat:
qemu-system-x86_64 -kernel $LINUX_BUILD/arch/x86_64/boot/bzImage \
-initrd $BUILDS/initramfs.cpio.gz -nographic \
-append "console=ttyS0" -enable-kvm
...
Boot took 0.45 seconds
_ _ __ _
/\/\ (_)_ __ (_) / /(_)_ __ _ ___ __
/ \| | '_ \| | / / | | '_ \| | | \ \/ /
/ /\/\ \ | | | | | / /__| | | | | |_| |> <
\/ \/_|_| |_|_| \____/_|_| |_|\__,_/_/\_\
Welcome to mini_linux
/ # ls /
bin etc linuxrc root sys
dev init proc sbin usr
/ # QEMU: Terminated
Vi antar att en verktygskedja är tillgänglig i/opt/toolchains/x86_64-unknown-linux-gnu
med prefix x86_64-unknown-linux-gnu
, gcc-version 5.x, kärn-headers 4.3.x, biblioteket glibc C och stöd för C++. Detta är rimliga standardvärden om du använder en verktygskedja genererad av crosstool-NG. Anpassa efter din egen situatuon. Viktigt:
- Du kan inte använda din värddators ursprungliga verktygskedja (se dokumentationen för Buildroot för att förstå varför).
- Om du inte redan har en verktygskedja kan du bygga en med crosstool-NG (eller själva Buildroot) och använda den senare för andra projekt.
- crosstool-NG är det rekommenderade verktyget för att bygga en egen verktygskedja, men undvik att använda uClibc (inget IPV6-stöd) och föredra uClibc-ng eller glibc.
- Ydu kan också använda den inbyggda verktygskedjan från Buildroot, men var medveten om att det kommer att ta längre tid än att använda en befintlig verktygskedja. Var också medveten om att i många fall kommer du att behöva bygga om verktygskedjan efter att ha modifierat Buildroot-konfigurationen.
- Ännu inte övertygad? Se crosstool-NG, bygg och använd din egen verktygskedja. Gå till denna gist för en snabbstart i crosstool-NG.
export BUILDROOT=$OPT/buildroot _här läggs källkoden för Buildroot_
export BUILDROOT_BUILD=$BUILDS/buildroot
mkdir -p $BUILDROOT_BUILD
cd $BUILDROOT_BUILD
touch Config.in external.mk
echo 'name: mini_linux' > external.desc
echo 'desc: minimal linux system with buildroot' >> external.desc
mkdir configs overlay
cd $BUILDROOT
make O=$BUILDROOT_BUILD BR2_EXTERNAL=$BUILDROOT_BUILD qemu_x86_64_defconfig
cd $BUILDROOT_BUILD
make menuconfig
Konfigurera Buildroot:
Build options ---> Location to save buildroot config ---> $(BR2_EXTERNAL)/configs/mini_linux_defconfig
Build options ---> Download dir ---> /some/where/buildroot_dl
Build options ---> Number of jobs to run simultaneously (0 for auto) ---> 8
Build options ---> Enable compiler cache ---> yes
Build options ---> Compiler cache location ---> /some/where/buildroot_ccache
Toolchain ---> Toolchain type ---> External toolchain
Toolchain ---> Toolchain ---> Custom toolchain
Toolchain ---> Toolchain origin ---> Pre-installed toolchain
Toolchain ---> Toolchain path ---> /opt/toolchains/x86_64-unknown-linux-gnu
Toolchain ---> Toolchain prefix ---> x86_64-unknown-linux-gnu
Toolchain ---> External toolchain gcc version ---> 5.x
Toolchain ---> External toolchain kernel headers series ---> 4.3.x
Toolchain ---> External toolchain C library ---> glibc/eglibc
Toolchain ---> Toolchain has C++ support? ---> yes
System configuration ---> System hostname ---> mini_linux
System configuration ---> System banner ---> Welcome to mini_linux
System configuration ---> Run a getty (login prompt) after boot ---> TTY port ---> ttyS0
System configuration ---> Network interface to configure through DHCP --->
System configuration ---> Root filesystem overlay directories ---> $(BR2_EXTERNAL)/overlay
Kernel ---> Linux Kernel ---> no
Filesystem images ---> cpio the root filesystem (for use as an initial RAM filesystem) ---> yes
Filesystem images ---> Compression method ---> gzip
Spara konfigurationen:
make savedefconfig
Lägg till ett skript i katalogen overlay,$BUILDROOT_BUILD/overlay/init
med följande konfiguration:
#!/bin/sh
/bin/mount -t devtmpfs devtmpfs /dev
/bin/mount -t proc none /proc
/bin/mount -t sysfs none /sys
exec 0</dev/console
exec 1>/dev/console
exec 2>/dev/console
cat <<!
Boot took $(cut -d' ' -f1 /proc/uptime) seconds
_ _ __ _
/\/\ (_)_ __ (_) / /(_)_ __ _ ___ __
/ \| | '_ \| | / / | | '_ \| | | \ \/ /
/ /\/\ \ | | | | | / /__| | | | | |_| |> <
\/ \/_|_| |_|_| \____/_|_| |_|\__,_/_/\_\
Welcome to mini_linux
!
exec /bin/sh
Bygg root-filsystemet:
chmod +x overlay/init
time make
...
real 1m52.905s
user 0m50.682s
sys 0m36.928s
qemu-system-x86_64 -kernel $LINUX_BUILD/arch/x86_64/boot/bzImage \
-initrd $BUILDROOT_BUILD/images/rootfs.cpio.gz -nographic \
-append "console=ttyS0"
Kommentar: för bättre prestanda, lägg tll flaggan -enable-kvm
om din värd har KVM aktiverat.
...
Boot took 0.57 seconds
_ _ __ _
/\/\ (_)_ __ (_) / /(_)_ __ _ ___ __
/ \| | '_ \| | / / | | '_ \| | | \ \/ /
/ /\/\ \ | | | | | / /__| | | | | |_| |> <
\/ \/_|_| |_|_| \____/_|_| |_|\__,_/_/\_\
Welcome to mini_linux
/ # ls /
bin init linuxrc opt run tmp
dev lib media proc sbin usr
etc lib64 mnt root sys var
/ # QEMU: Terminated
Skapa en ny katalog för ditt program:
export APPS=$BUILDS/apps
mkdir -p $APPS
cd $APPS
Lägg till källkoden för ett program, $APPS/hello_world.c
med följande innehåll:
#include <stdio.h>
int main(int argc, char **argv) {
printf("mini_linux says: Hello world!\n");
return 0;
}
Lägg till en make-file, $APPS/Makefile
med följande innehåll (ersätt defintitionenCROSS_COMPILE
med det som passar i ditt specifika fall):
CROSS_COMPILE := /opt/toolchains/x86_64-unknown-linux-gnu/bin/x86_64-unknown-linux-gnu-
CC := $(CROSS_COMPILE)gcc
hello_world: hello_world.o
$(CC) -o $@ $<
hello_world.o: hello_world.c
$(CC) -c -o $@ $<
clean:
rm -f hello_world hello_world.o
Kompilera programmet, kopiera in det in katalogen overlay i Buildroot och bygg om root-filsystemet:
make
...
cp hello_world $BUILDROOT_BUILD/overlay
...
cd $BUILDROOT_BUILD
make
qemu-system-x86_64 -kernel $LINUX_BUILD/arch/x86_64/boot/bzImage \
-initrd $BUILDROOT_BUILD/images/rootfs.cpio.gz -nographic \
-append "console=ttyS0"
Kommentar: för bättre prestanda, lägg till flaggan -enable-kvm
om din värd har KVM aktiverad.
...
Boot took 0.57 seconds
_ _ __ _
/\/\ (_)_ __ (_) / /(_)_ __ _ ___ __
/ \| | '_ \| | / / | | '_ \| | | \ \/ /
/ /\/\ \ | | | | | / /__| | | | | |_| |> <
\/ \/_|_| |_|_| \____/_|_| |_|\__,_/_/\_\
Welcome to mini_linux
/ # ls
bin init media root tmp
dev lib mnt run usr
etc lib64 opt sbin var
hello_world linuxrc proc sys
/ # ./hello_world
mini_linux says: Hello world!
/ # QEMU: Terminated
cd $LINUX_BUILD
make menuconfig
Ändra kärnkonfigurationen:
Enable loadable module support ---> yes
Bygg om kärnan och dess moduler (ingen i vårat fall) och installera dem i katalogen overlay i Buildroot:
make -j8
make -j8 modules
make modules_install INSTALL_MOD_PATH=$BUILDROOT_BUILD/overlay
Skapa en ny katalog för den egna kärnmodulen:
export MODULES=$BUILDS/modules
mkdir -p $MODULES
cd $MODULES
Lägg till källkodsfilen för en modul, $MODULES/hello_world.c
med följande innehåll:
/* hello_world.c */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
static int __init first_init(void)
{
pr_info("mini_linux module says: Hello world!\n");
return 0;
}
static void __exit first_exit(void)
{
pr_info("Bye\n");
}
module_init(first_init);
module_exit(first_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("My first module");
MODULE_AUTHOR("The Doctor");
Lägg till en make-fil, $MODULES/Makefile
med följande innehåll:
ifneq ($(KERNELRELEASE),)
# kbuild part of makefile
obj-m := hello_world.o
else
# normal makefile
KDIR ?= $(LINUX_BUILD)
default:
$(MAKE) -C $(KDIR) M=$$PWD
modules_install:
$(MAKE) -C $(KDIR) M=$$PWD $@
clean:
rm -rf *.o .*.cmd *.ko hello_world.mod.c modules.order Module.symvers .tmp_versions
endif
Kompilera modulen, installera den i Buildroots overlay-katalog och bygg om root-filsystemet:
make
...
make modules_install INSTALL_MOD_PATH=$BUILDROOT_BUILD/overlay
...
cd $BUILDROOT_BUILD
make
qemu-system-x86_64 -kernel $LINUX_BUILD/arch/x86_64/boot/bzImage \
-initrd $BUILDROOT_BUILD/images/rootfs.cpio.gz -nographic \
-append "console=ttyS0"
Kommentar: för bättre prestanda, lägg till flaggan -enable-kvm
om din värd har KVM aktiverat.
...
Boot took 0.57 seconds
_ _ __ _
/\/\ (_)_ __ (_) / /(_)_ __ _ ___ __
/ \| | '_ \| | / / | | '_ \| | | \ \/ /
/ /\/\ \ | | | | | / /__| | | | | |_| |> <
\/ \/_|_| |_|_| \____/_|_| |_|\__,_/_/\_\
Welcome to mini_linux
/ # ls lib/modules/4.8.0\+/extra
hello_world.ko
/ # lsmod
Module Size Used by Not tainted
/ # insmod lib/modules/4.8.0\+/extra/hello_world.ko
hello_world: loading out-of-tree module taints kernel.
mini_linux module says: Hello world!
/ # lsmod
Module Size Used by Tainted: G
hello_world 704 -
/ # QEMU: Terminated
Se denna gist för hur du kan använda extlinux för att installera din distribution på t.ex en USB-lagringsenhet
Denna instruktion bygger på material från https://gist.github.com/pacalet/660fa6472e0bcd53f71fc31f167c628f