The goal of this gist is to introduce you to building your first Linux kernel and installing it on an Ubuntu Linux virtual machine.
We assume the presence of the following tools:
-
Access to a Linux machine to build the kernel
- On this machine, install the following packages (assuming it's an Ubuntu machine):
sudo apt install libncurses5-dev gcc make git exuberant-ctags bc libssl-dev
- Since we're already installing things, let's go ahead and install
vim
andcscope
sudo apt install vim cscope
- On this machine, install the following packages (assuming it's an Ubuntu machine):
-
Access to an Ubuntu virtual machine. You can use VirtualBox or any other virtualization technology. At this step, host refers the machine that is running VirtualBox while guest refers to the machine that is virtually running in of VirtualBox.
- It is best not to use a virtual machine for compiling the kernel since compilation will be resource intensive and would take forever on a non well-provisioned machine.
- Create a new virtual machine using the VirtualBox GUI and install any Ubuntu distribution on it. For faster results, it is better to work with the Ubuntu server edition. You can download the latest Ubuntu server edition (18.04.1) from the official Ubuntu repo.
- After the vm has started, login and check the IP address of the machine and record it:
ifconfig -a
- From the host machine, make sure that you can reach the vm via the virtual network. To check
that, assume that 192.168.122.1 is the IP address of the vm, from a terminal on the host
machine, do
If the ping does not go through, then the connection is not successful and we might need to do some more configuration. If the connection goes through, check that you can ssh into the virtual machine using where
ping -c1 192.168.122.1
user
is the username used when creating the virtual machine.
Download the latest kernel from the official kernel source.
-
From the host machine, download the kernel into a directory using
wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.18.6.tar.xz
-
Extract the contents of the kernel source tree
tar -xvf linux-4.18.6.tar.xz
-
This will create the directory
linux
. Change into that directory and let's start compiling the kernel. First let's copy the default configuration file from the current host machine (Note: Only do this if the host machine is running a Linux machine).cd linux/ cp /boot/config-`(uname -r)` .config
-
Let's feed the config file to the kernel build mechanism
yes '' | make oldconfig
The command
yes ''
will answer all the questions of the configurations options that are missing with the default values. -
If the host machine is not running Linux, then you can use
make defconfig
to use the default configuration files included with the kernel.
-
Now it's time to start the long build step. If you are on a remote server, then to make sure that the process is not killed if the remote session is broken, we need to run our process in the background. To do so, we can either use
tmux
orscreen
. Sincetmux
provides a richer set of features (imo), we will go withtmux
.- To install tmux in case it was not installed:
sudo apt install -y tmux
- Start a new tmux session
tmux new -s kernelbuild
kernelbuild
is the name of our session so we can pick it up later. This will drop you into a new session that you can leave running in the background if desired.
- To install tmux in case it was not installed:
-
Now let's build the kernel. To start compilation, we will use the
make
utility (well we alerady kinda did), so usemake -j $(getconf _NPROCESSORS_ONLN) deb-pkg LOCALVERSION=-custom
- You can replace
custom
with anything you would want to appear appended to your custom kernel version. - This will start printing all kinds of compilation things and the process has started.
If you are running this inside of a
tmux
session, you can detach from that session using the keyboard combination
where<C-b> d
<C-b>
is the tmux's bind key, and by default this is theControl
key pressed with theb
key. So the key combination becomesControl + b
thend
. - To check the current running tmux sessions use
It should print something like
tmux ls
kernelbuild: 1 windows (created Thu Sep 6 20:41:56 2018) [238x60]
- To reattach to a running tmux session use
If
tmux at -t kernelbuild
kernelbuild
is the only session running, thentmux at
will drop you directly into that session.
- You can replace
-
Grab a cup of coffee and enjoy the break while waiting for the compilation to end. It might take a while. It's always good to bring out the classic compilation xkcd:
Once the compilation completes without errors, then congratulations, you have just compiled your
first kernel. If you go up one directory (cd ..
), you should see the following files pop-up:
../linux-4.18.6-custom_4.18.6-custom-1.diff.gz
../linux-4.18.6-custom_4.18.6-custom.orig.tar.gz
../linux-image-4.18.6-custom_4.18.6-custom-1_amd64.deb
../linux-libc-dev_4.18.6-custom-1_amd64.deb
../linux-4.18.6-custom_4.18.6-custom-1.dsc
../linux-headers-4.18.6-custom_4.18.6-custom-1_amd64.deb
../linux-image-4.18.6-custom-dbg_4.18.6-custom-1_amd64.deb
The files we care about are the ones that end with .deb
extension. These are the files that we
will use for installing the kernel on the virtual machine. Specifically, the ones we really need are
../linux-image-4.18.6-custom_4.18.6-custom-1_amd64.deb
../linux-headers-4.18.6-custom_4.18.6-custom-1_amd64.deb
So let's copy those files to the virtual machine
scp linux-image-*.deb [email protected]:~/
scp linux-headers-*.deb [email protected]:~/
Remember to replace user
and 192.168.122.1
with the username and the IP address used for the
virtual machine you have created. scp
is the "secure copy" utility that will copy files over a
network.
Next, let's log into the virtual machine and install the kernel
Once in the vm, the .deb
packages should be in the home directory, then let's install them all in
one shot
sudo dpkg -i *.deb
where dpkg
is the Debian-based package manager (for installing software) and the flag -i
signals to
the manager that we want to install the deb packages. Finally *.deb
means that we will install all
files that end with .deb
(the * means the Kleen Star).
After installation ends, we need to refresh our grub
configuration, so we can do that with
sudo update-grub
grub
is the default bootloader for Linux systems, it takes
care of loading the right stuff at
startup time.
Now let's restart the virtual machine
sudo reboot
At this stage you will be disconnected from the vm so you should ssh back into it after it has restarted. Once you log back in, you can check which kernel you are running using
uname -r
which should show something like
4.18.6-custom