The Linux kernel is the heart of the operating system, responsible for managing system resources and communicating with hardware. While the default kernel that comes with most Linux distributions works for most users, it may not be optimized for your particular hardware or usage. That's where building a custom kernel comes in. By compiling your own kernel, you can fine-tune it to your specific needs, resulting in improved performance, stability, and security. In this article, we'll provide a quick and easy introduction to building a custom kernel using the "localmodconfig" target with the output of lsmod, allowing you to get under the hood of your Linux system and unlock its full potential.
The Linux kernel is like the traffic cop of your operating system, directing the flow of data between your computer's hardware and software. It's the bridge that connects applications with the physical resources of the machine, like the CPU, memory, and storage. The kernel is made up of several components, each with its own set of responsibilities. The core component is the scheduler, which allocates resources to different processes and ensures that they run smoothly. Other key components include the memory manager, which manages memory allocation and deallocation, and the device driver framework, which allows hardware devices to communicate with the kernel and the rest of the system. In addition to these core components, the kernel is also made up of various modules that can be loaded and unloaded on demand. These modules add functionality to the kernel and allow it to support a wide range of hardware and software configurations. Understanding the basic structure of the kernel and its different components is important for building a custom kernel, as it allows you to choose which features and modules to include or exclude based on your specific needs.
Before we can build a custom kernel, we first need to obtain the kernel source code. One easy way to do this is by using the wget command to download it from a trusted source. For example, you can use the following command to download version 6.2.8 of the Linux kernel:
# download the kernel source from kernel.org's CDN
user@darkstar:~/$ wget -c https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.2.8.tar.xz
Once the download is complete, you can extract the source code using the tar command:
# unpack the kernel source code
user@darkstar:~/$ tar -xvf linux-6.2.8.tar.xz
# change into the source code directory
user@darkstar:~/$ cd linux-6.2.8
This will create a new directory called "linux-6.2.8" that contains all the source code for the kernel. From here, you can start configuring and building your custom kernel. Note that the specific version of the kernel you download may vary depending on your needs and the hardware and software configuration of your system. You should always download the kernel source code from a trusted source, such as the official Linux kernel website. Now that we have the kernel source code, we can start building our custom kernel using the localmodconfig target and the output of the lsmod command.
First, we need to generate a list of currently loaded kernel modules using the lsmod command. To save the output of the lsmod command to a text file, you can use the following command:
# redirect the output of lsmod to text file
user@darkstar:~/linux-6.2.8$ lsmod > mylsmod.txt
This will create a file called "modules.txt" in your current working directory that contains a list of all currently loaded kernel modules.
Next, we can use the localmodconfig target to create a custom kernel configuration file based on the currently loaded modules. To do this, we'll use the following command:
# create the configuration file using lsmod ouput
user@darkstar:~/linux-6.2.8$ make LSMOD=/path/to/modules.txt O=/home/user/build localmodconfig
Replace "/path/to/modules.txt" with the actual path to the "modules.txt" file that you generated earlier. This will create a custom kernel configuration file that includes only the modules currently loaded on your system.
Once the custom configuration file is generated, we can start building the kernel using the following commands:
# now we can build the kernel and modules
user@darkstar:~/linux-6.2.8$ time make O=/home/user/build
# install the kernel modules
user@darkstar:~/linux-6.2.8$ sudo make O=/home/user/build modules_install
# I don't use 'make install' to install kernel as it may delete the current
# kernel files, leaving you without a working kernel if the new kernel won't boot
# copy kernel image to /boot
user@darkstar:~/linux-6.2.8$ sudo cp /home/user/build/arch/x86/boot/bzImage /boot/vmlinuz-6.2.8
# copy System.map file to /boot
user@darkstar:~/linux-6.2.8$ sudo cp /home/user/build/System.map /boot/System.map--6.2.8
# copy this kernel's config file to /boot
user@darkstar:~/linux-6.2.8$ sudo cp /home/user/build/.config /boot/config-6.2.8
The "O=/home/user/build" option tells make to keep the compiled kernel binaries separate from the kernel source code, and to place them in the "/home/user/build" directory instead. Note that these commands may take some time to complete, depending on the speed of your system and the complexity of your custom kernel configuration. By following these steps, you can quickly and easily build a custom kernel that is tailored to your specific hardware and software configuration, and that includes only the modules that are currently loaded on your system.
Once the custom kernel is built, we need to test and install it on our system. First, we need to create an initial RAM disk (initrd) image using Slackware Linux's mkinitrd command. This initrd image is used to load essential drivers and modules required for booting the system into the new kernel. To create an initrd image, we can use the following command:
# generate and initial ramdisk image (initrd or intraramfs)
# this is the Slackware command, refer to your distro's documentation
# for instructions on how to build initrd for your distro
user@darkstar:~/linux-6.2.8$ sudo mkinitrd -c -k 6.2.8 -r /dev/nvme0n1p2 -f xfs -m xfs:usbhid:hid-generic:amdgpu -u -o /boot/initrd-6.2.8.gz
This command creates an initrd image for kernel version 5.13.0, using the ext4 file system driver and the ahci module. Replace "/dev/sda1" with the actual root partition of your system.
Once the initrd image is created, we need to edit the grub.cfg file to add an entry for the new kernel. The grub.cfg file is usually located in the /boot/grub/ directory. Open the file with your preferred text editor and add a new menu entry for the new kernel. The entry should look something like this:
# add the following to your grub.cfg file
menuentry 'Custom Kernel 5.13.0' {
set root='hd0,gpt1'
linux /boot/vmlinuz-5.13.0 root=/dev/sda1
initrd /boot/initrd-5.13.0
}
Replace "hd0,gpt1" with the actual partition and file system where your /boot directory is located. Replace "vmlinuz-5.13.0" and "initrd-5.13.0" with the actual file names of your custom kernel and initrd image. Save the changes to the grub.cfg file and exit the text editor. Finally, reboot your system and select the new kernel from the GRUB menu. If everything was configured correctly, your system should boot into the new kernel with all your custom modules and drivers loaded.
In conclusion, building a custom kernel offers a wide range of benefits, including improved performance and customized features. In this article, we have discussed how to build a custom kernel using the localmodconfig target with the output of lsmod. By using this method, we can quickly and easily build a custom kernel that includes only the necessary modules for our system. We have also seen how to test and install the custom kernel on our system, including creating an initrd image and editing the grub.cfg file. We encourage readers to try building their own custom kernel and experiment with different configurations to optimize their system's performance and functionality. Building a custom kernel may seem daunting at first, but with the right tools and guidance, it can be a simple and rewarding experience.
-- JuanKenobi