How to compile Linux kernel¶
This tutorial is intended to help students to install the tools and the adequate environment to build the Linux kernel. In addition, it provides the steps to compile the Linux kernel.
Tip
Please have a first look on the slides before doing the tutorial.
There exist several ways to compile the Linux kernel. In this tutorial, we will explain two different ways:
Compiling the kernel on NON-reference image: The first way requires two Linux machines. One is either a virtual machine (VM) or the bare metal OS (dual-boot) and is used for kernel development and compilation (as the compilation is very slow, a dual boot is preferred). The other is a VirtualBox VM which contains a reference image and which is used for kernel testing. For this case, see the conventions before starting the tutorial.
Compiling the kernel on the reference image: The other way is to work directly on the reference image within a virtual machine (VM). You will develop, compile and test the kernel in the same environment.
Danger
The new kernel will be tested with VirtualBox. The virtual machine is Ubuntu 32 bits. The reference image can be downloaded here. Only this image, which is a 32 bits Ubuntu, must be used for testing. The user is student
and the password is student
.
Method1: Compiling the kernel on NON-reference image¶
In this method, some commands are entered in the host machine, and others in the virtual machine. The conventions are the following:
host$ command # in the terminal of the host machine
virtual$ command # in the terminal of the virtual machine
Caution
If you have Windows or Mac OS, you can hack the kernel on your host machine nevertheless we strongly encourage you to develop inside a Linux environment in order to avoid /r
or /n/r
Mac/Windows problems, hidden Mac OS files, … In that case you need to use 2 VMs (see Slides).
Download the kernel sources¶
The first step is to download and extract the kernel 4.15 sources in your host machine by typing the following commands:
host$ mkdir /home/username/OS
host$ cd /home/username/OS
host$ wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.15.tar.xz
host$ tar -Jxvf linux*
host$ cd linux*
Configure a Git folder¶
In order to generate/apply patches, you need to save the initial state of this folder using Git. Enter the following commands to do it:
host$ cd linux*
host$ git config --global user.name "Your Name" # Configuration
host$ git config --global user.email "you@example.com" # Configuration host$ git init
host$ git add .
host$ git commit -m "first commit" # Saving the initial state
host$ git log
Installing the requirements¶
In order to compile the kernel, we’ll need to first install a few requirements. This can be done with a single command:
host$ sudo apt install build-essential libncurses5-dev libssl-dev flex libelf-dev bison gcc make
Sharing host files with the reference VM¶
In order to build and launch a custom kernel on a VM, it is necessary to transfer your source files. There exist several methods to do it but in that case we only explain sshfs and rsync. Refer to the slides for further information.
Using sshfs¶
sshfs establishes a secure link to a machine where you have an account, and make a sub-tree of this machine’s filesystem appear as a sub-tree on the calling machine. It thus allows to mount a remote VM directory on the local machine. In other words, we can use GUI based editors for development. Use the following commands to setup a sshfs tunnel:
host$ mkdir /home/username/OS # Only if the folder has not yet been created
virtual$ mkdir /home/student/OS
virtual$ sshfs -o allow_other username@{host_ip}:/home/username/OS /home/student/OS
By default, only the user who invoked sshfs can access this sub-tree. E.g., if you invoke it as student on your virtual machine, root may not be able to read content from remote. To allow root to read the content, use the following option
-o allow_other
or -o allow_root
.
We can unmount the mounted remote directory with the following command:
host$ fusermount -u ~/home/username/OS
Caution
We cannot find out the proper way to setup sshfs on Windows… Sorry.
Using rsync¶
The second way to share host files is to use rsync. This one is an open source utility that provides fast incremental file transfer. In opposite to sshfs, rsync does only copy therefore you need to execute it after each change/update. Use the following commands to use rsync:
host$ mkdir /home/username/OS # Only if the folder has not yet been created
virtual$ mkdir /home/student/OS
virtual$ rsync -rapvC username@{host_ip}:/home/username/OS /home/student/OS
Configuring the kernel¶
Before we actually compile the kernel, we must first configure it. The Linux kernel configuration is usually found in the kernel source in the .config
file. In that case, we already generated the righ configuration in order to save a lot of time. Enter the following commands in order to configure your kernel:
host$ wget http://www.montefiore.ulg.ac.be/~yasukata/lecture/asset/INFO0940_2020/misc/linux-4.15-32bit-config
host$ mv linux-4.15-32bit-config .config
host$ make olddefconfig
Build the kernel¶
Now it’s time to actually compile the kernel. Use the make
command. Specify the number of threads (-j
option) and the architecture (32bits). The -j
option is only use to speed up application build, it determines how many jobs can spawn for the build. You can either set -j <nb_cores>
or even higher -j <nb_cores * 1.5>
in order that the compilation can happen in parallel. Enter the following commands in your kernel folder:
host$ make ARCH=i386 bzImage -j4
Then, compile the modules (you’ll need to compile them again only if you modify files chosen to be compiled as modules):
host$ make ARCH=i386 modules -j4
Installing the kernel¶
If you type the normal make install && make modules_install
, it will install it in your host! Instead, we’ll install the files in a temporary directory so you can copy them to the virtual machine after that:
host$ mkdir /home/username/OS/boot
host$ export INSTALL_PATH=/home/username/OS/boot
host$ mkdir /home/username/OS/mods
host$ export INSTALL_MOD_PATH=/home/username/OS/mods
host$ make modules_install
host$ make install
Assuming your sshfs is still working and is configured with the allow_other
or allow_root
option, type the following commands:
virtual$ cd /home/student/OS
virtual$ sudo cp -rf boot/* /boot
virtual$ sudo cp -rf mods/* /
If you haven’t allow_root
options or have others “sudo” and permission-related problem, first copy files to /tmp
as normal user, then copy them from /tmp
to their final destination. Finally, we make the initrd image and tell GRUB (the bootloader) to update itself with the following commands:
virtual$ sudo update-initramfs -u -k 4.15.0+
virtual$ sudo update-grub
virtual$ sudo reboot
Checking your current version¶
In order to check if the new version of your kernel is correctly installed, use the uname
command
virtual$ uname -a
Linux student 4.15+ #1 SMP Tue Jan 29 09:41:40 JST 2020 i686i686 i686 GNU/Linux
If you still see kernel version 4.4, please choose 4.15 from the grub menu which is the black screen at the boot phase.
Method2: Compiling the kernel on the reference image¶
Important
This method is globally quite similar to the previous one except that you must execute all commands on the virtual machine. Therefore, the rsync/sshfs sections must be skipped. In addition, when installing the kernel, you just need to execute make install on the virtual machine (you must skip the copy with sshfs). We have written a small script which does all the job. You can refer to the slides if you are a bit lost.
The following commands compile and install a new kernel on your virtual machine. After the procedure is finished, please reboot your VM for loading the new kernel. If you are busy, you just need to type the following 4 lines of commands, and do not need to check further :) Execute the following commands on your VM:
$ cd ~
$ wget http://www.montefiore.ulg.ac.be/~yasukata/lecture/asset/INFO0940_2020/howto/compilekernel/compile_kernel.sh
$ chmod 755 ./compile_kernel.sh
$ ./compile_kernel.sh
Danger
If you compile and install on the same VM, don’t forget to do an initial snapshot of the reference VM. Please, see the following link. In addition, you need to use git to have a copy of your files. If you DON’T use Git, you can lose your files in case of kernel panic (trust me, it’s quite frequent).
What’s done by the script?¶
The script carries out 7 steps (Please also refer to the comments in the script):
Install the required packages
For kernel compilation, at least we need gcc, make, libssl-dev, flex, bc, and bison. In Ubuntu, we can use the
apt
command for installing packages. xz-utils is needed for extracting the kernel source. git is used for making patches that to be submitted as your homework.Download kernel source
The source code of Linux is found at the Linux Kernel Archives https://www.kernel.org/. On the web page, we can explore varied versions and branches of the Linux kernel. In this time, we download the source from a specific URL https://cdn.kernel.org/pub/linux/kernel/v4.x/${KERNEL}.tar.xz which gives us a specific version of the kernel. On Linux, we can use the
wget
command for downloading content over HTTP.Extract kernel source
The downloaded source is compressed in the xz format. We can extract by using the tar command with the “xvf” option.
Prepare a config file
For compiling the Linux kernel, we always need to prepare a config file. The config file allows us to choose features to be enabled. When we compile a kernel, we make a config file from old version of config file. In this time, we download the one prepared by the TAs. Alternatively we can use by copying one of config files in
/boot
. The commandmake olddefconfig
is typed for adjusting the old version of config file (downloaded one) to the kernel that we are about to compile.Compile kernel
Now, preparation is done, so let’s start compilation. All compilation is done by a single command
make
.Install kernel
Finally, we install the built kernel by
make modules_install
andmake install
. The commandmake modules_install
installs kernel modules, andmake install
installs the kernel itself.
Further informations¶
For booting a new kernel, essentially we need the new kernel image, initial ramdisk (initrd), and kernel modules including device drivers.
The command
make modules_install
makes the following directory that retains kernel modules.
/lib/modules/KERNEL_VERSION
In the installation process,
make install
produces the following files in your system.
/boot/vmlinuz-KERNEL_VERSION
/boot/initrd.img-KERNEL_VERSION
vmlinuz is the compiled kernel. initrd (initial ramdisk) contains files used for bootup.
In general, OSes are loaded by boot loaders. On Linux, GRUB is widely used, and for loading the newly built kernel, we need to reconfigure GRUB.
make install
performs reconfiguration of GRUB. Usually, a new boot entry is added for the new kernel.In short,
make modules_install
installs kernel modules at/lib/modules/
, andmake install
locates the kernel image on/boot
, and updates configuration of the boot loader.
How to Re-Compile Linux Kernel¶
While you are working on your assignment, you will recompile your kernel for debugging. If you compile the kernel once, you do not need to repeat the entire process, and you can skip Step 1, 2, 3, and 5. In short, you can use the following script which cuts unnecessary steps.
#!/bin/bash
KERNEL=linux-4.15
# go to user home directory
cd ~
# Step 4: enter kernel source directory
cd ${KERNEL}
# Step 6: kernel compilation (only for the image)
make ARCH=i386 bzImage -j4
# Step 7: kernel installation
# Step 7.1: install kernel modules
sudo make modules_install -j4
# Step 7.2: install kernel itself
sudo make install