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
vimandcscopesudo 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
useris 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
tmuxorscreen. Sincetmuxprovides 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
kernelbuildis 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
makeutility (well we alerady kinda did), so usemake -j $(getconf _NPROCESSORS_ONLN) deb-pkg LOCALVERSION=-custom- You can replace
customwith 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
tmuxsession, 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 theControlkey pressed with thebkey. So the key combination becomesControl + bthend. - 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
kernelbuildis the only session running, thentmux atwill 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.debThe 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.debSo 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 *.debwhere 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-grubgrub 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 -rwhich should show something like
4.18.6-custom
