LPIC-2 Linux Kernel: Components, Compiling, Modules, and sysctl Tuning
- Build and install a kernel in the correct order, and explain why modules_install can't be skipped
- Choose between modprobe and insmod, and inspect modules with modinfo and lsmod
- Set module options and blacklist a driver in /etc/modprobe.d/
- Tune kernel parameters at runtime and persist them so they survive a reboot
What the kernel is, and why you'd ever rebuild it
Frame the kernel as the layer everything else trusts, and name the two ways you change it.
The kernel is the program that owns the hardware. Every other process talks to disks, network cards, and memory by asking the kernel to do it on their behalf. Think of the kernel as the building's electrical and plumbing system: applications are tenants who flip switches and turn taps, but the wiring and pipes behind the walls are shared infrastructure that one team controls.
You change kernel behaviour two ways, and LPIC-2 tests both:
- At build time — compile a new kernel (or new drivers) from source. Heavy, occasional, done when you need hardware support or a feature the distro kernel lacks.
- At run time — load modules (drivers you snap in and out of a running kernel) and set sysctl parameters (tunable knobs like network and memory behaviour) without rebooting.
This lesson walks the build flow first, then the everyday module and tuning workflow.
The build flow, in order
Run the four build steps in sequence and understand what each one produces.
Compiling a kernel is four commands in a fixed order. Each feeds the next, like a production line: configure what to build, build it, install the parts (modules), then install the kernel itself so the bootloader can find it.
Example — not runnable on your lab box
make oldconfigscripts/kconfig/conf --oldconfig Kconfig # # configuration written to .config #
- oldconfig
- Start from the existing .config and only ask about options that are new in this source tree.
This produces the `.config` file — the answer sheet of which features and drivers to compile. oldconfigreuses your current kernel's choices and prompts only for genuinely new options, so you're not re-answering thousands of questions. Nothing is compiled yet; you've only decided what to compile.Example — not runnable on your lab box
make -j$(nproc)... LD vmlinux SORTTAB vmlinux OBJCOPY arch/x86/boot/bzImage Kernel: arch/x86/boot/bzImage is ready
- -j N
- Run N compile jobs in parallel. More jobs = faster build on multi-core machines.
- $(nproc)
- Substitutes the CPU core count, so -j matches the cores you actually have.
This is the long step: it compiles the kernel image ( bzImage) and every driver you marked as a module (.kofiles).-j$(nproc)uses all your cores — on an 8-core box that's roughly 8x faster than a single-threaded build. When it finishes, the compiled artifacts exist in the source tree but aren't installed anywhere the system looks.Example — not runnable on your lab box
sudo make modules_installINSTALL /lib/modules/6.8.0-custom/kernel/fs/xfs/xfs.ko INSTALL /lib/modules/6.8.0-custom/kernel/net/... DEPMOD 6.8.0-custom
- modules_install
- Copy every compiled .ko module into /lib/modules/<version>/ and run depmod.
This copies the compiled modules into `/lib/modules/<kernel-version>/` — the only place a running kernel looks for its drivers — and runs depmodto build the dependency map. Notice the `DEPMOD` line at the end: that's the system recording which module needs which, the datamodprobewill rely on later.Example — not runnable on your lab box
sudo make installINSTALL /boot/vmlinuz-6.8.0-custom INSTALL /boot/initramfs-6.8.0-custom.img Generating grub configuration file ... done
- install
- Copy the kernel image to /boot, build the initramfs, and update the bootloader.
The final step copies the kernel image into `/boot`, generates an initramfs, and updates the bootloader (GRUB) so the new kernel appears in the boot menu. Now the system can actually boot the kernel you built.Check yourself
You compiled and installed a new kernel but forgot
make modules_install. What goes wrong at the next boot?Loading modules: modprobe vs insmod
Pick the right loader by understanding which one resolves dependencies.
A module is a driver you can plug into the running kernel — no reboot, no recompile. But modules often depend on other modules (a filesystem driver may need a compression helper). Two tools load them, and the difference is entirely about dependencies.
Think of it like installing software:
modprobeis your package manager — ask for one thing and it pulls in everything that thing needs.insmodis copying a single file into place — it installs exactly what you named and nothing else.Example — not runnable on your lab box
sudo modprobe xfs- modprobe
- Load a module by name, resolving and loading its dependencies first.
- -r
- Remove (unload) a module and any now-unused dependencies it pulled in.
Silent success — no output means it worked. modprobelooked upxfsin `modules.dep` (the map built bydepmod), loaded any modulesxfsdepends on first, then loadedxfs. You name one module by its name (no path, no.ko) and it handles the chain.Example — not runnable on your lab box
sudo insmod /lib/modules/$(uname -r)/kernel/fs/xfs/xfs.koinsmod: ERROR: could not insert module .../xfs.ko: Unknown symbol in module
- insmod
- Insert exactly one .ko file by full path — no dependency resolution at all.
insmodtakes a full path to a single `.ko` file and loads only that file. Because it does no dependency resolution, ifxfsneeds another module that isn't already loaded, you get anUnknown symbolerror — the missing symbol lives in the dependencyinsmoddidn't load.modprobewould have loaded that dependency first and this would have just worked.Example — not runnable on your lab box
sudo modprobe -r xfsUnloading mirrors loading. modprobe -rremovesxfsand any dependencies it pulled in that nothing else is still using. The lower-level equivalent isrmmod xfs, which removes a single module (and complains if something still depends on it).Check yourself
Which command loads a module AND automatically pulls in the other modules it depends on?
Inspecting modules: modinfo and lsmod
Find out what a module does and whether it's currently loaded — before you touch it.
Before loading or blacklisting a driver, you want two facts: what is this module and what options does it accept (
modinfo), and is it loaded right now and what's using it (lsmod). Look before you leap.Example — not runnable on your lab box
modinfo xfsfilename: /lib/modules/6.8.0/kernel/fs/xfs/xfs.ko license: GPL description: SGI XFS with ACLs, security attributes... depends: libcrc32c parm: bug_on_assert:Bug on assert (bool)
- modinfo
- Print a module's metadata: file path, license, description, dependencies, and parameters.
modinforeads the module's built-in metadata without loading it. The fields that matter: `depends:` lists modules this one needs (herelibcrc32c) — exactly whatmodproberesolves andinsmodignores. `parm:` lists the options you can pass the module — the names you'd set in/etc/modprobe.d/in the next step.lsmod | headModule Size Used by xfs 2179072 1 libcrc32c 16384 1 xfs nf_conntrack 172032 2 nf_nat,nf_tables
- lsmod
- List modules currently loaded into the running kernel (a formatted view of /proc/modules).
Three columns. Module is the name, Size is its memory footprint, and `Used by` is the count and names of things depending on it. Here libcrc32cshows1 xfs— one user, namelyxfs. ThatUsed bycount is whyrmmod xfsmust come before you can removelibcrc32c: you can't pull out a module something still depends on.Check yourself
Which command shows you a module's accepted parameters and dependencies WITHOUT loading it?
Module options and blacklists in /etc/modprobe.d/
Pass options to a module and stop an unwanted driver from loading — persistently.
Loading a module by hand is temporary. To make a module always load with certain options, or to stop a driver from ever loading, you write config files in `/etc/modprobe.d/` — any
*.conffile there is read bymodprobe. Two directives do most of the work:options <module> <key>=<value>— set parameters whenever the module loads.blacklist <module>— prevent the module from being loaded automatically.
Example — not runnable on your lab box
cat /etc/modprobe.d/blacklist-custom.conf# Stop the legacy framebuffer driver from grabbing the GPU blacklist nouveau # Always disable IPv6 in the module options ipv6 disable=1
Two directives in one file. `blacklist nouveau` tells modprobenot to auto-load thenouveaudriver — the usual move before installing a proprietary GPU driver that wants the card to itself. `options ipv6 disable=1` sets thedisableparameter (one of theparm:linesmodinfowould show) every timeipv6loads. The filename is arbitrary as long as it ends in.conf.Check yourself
Which directive in an /etc/modprobe.d/*.conf file passes parameters to a module each time it loads?
sysctl: runtime tuning vs persistent tuning
Set a kernel parameter now, then make it survive a reboot the right way.
sysctlreads and writes kernel tunables — knobs for networking, memory, and more, exposed under/proc/sys/. The single most-tested fact here is the split between runtime and persistent changes.Think of
sysctl -was writing on a whiteboard: instant, but wiped clean at the next reboot. Persisting a value is writing it into the building's manual so it's applied every time the building opens.sudo sysctl -w net.ipv4.ip_forward=1net.ipv4.ip_forward = 1
- -w
- Write (set) a kernel parameter immediately, in the running kernel only.
This turns on IP forwarding (routing packets between interfaces) right now. It's identical to running echo 1 > /proc/sys/net/ipv4/ip_forward— the keynet.ipv4.ip_forwardmaps directly to the file path/proc/sys/net/ipv4/ip_forward(dots become slashes). But this change lives only in memory.Example — not runnable on your lab box
cat /etc/sysctl.d/90-router.conf# Persist IP forwarding across reboots net.ipv4.ip_forward = 1
To make the change permanent, write the key = valueline into a*.conffile under `/etc/sysctl.d/`. This file is read at every boot, so the tunable is reapplied automatically. The filename's number prefix (90-) just controls ordering when multiple files set the same key — higher numbers win.sudo sysctl --system* Applying /etc/sysctl.d/90-router.conf ... net.ipv4.ip_forward = 1 * Applying /etc/sysctl.conf ...
- --system
- Reload and apply all sysctl config files from the standard directories, in order.
After editing a config file, sysctl --systemapplies all the files immediately so you don't have to reboot to test them. It walks/etc/sysctl.d/,/run/sysctl.d/,/usr/lib/sysctl.d/, and/etc/sysctl.conf, echoing each key it sets — confirming your file was picked up. Now the value is both live and persistent.sysctl net.ipv4.ip_forwardnet.ipv4.ip_forward = 1
Read a single tunable back by naming it with no -w. Reading is harmless and needs no root. This is how you verify a value actually took — the same ascat /proc/sys/net/ipv4/ip_forward.Check yourself
You set a tunable with
sysctl -wand it works, but it's gone after a reboot. What did you skip?Try it in your live terminal
Do it, don't just read it — these run read-only on the real sandbox to your right.
You have a real root shell. Run these in order. They are all read-only — they inspect the running kernel without changing it, so they're safe to run anywhere. The point is to make the inspect-before-you-touch moves reflex.
lsmod | headSee which modules are loaded right now, their size, and what depends on them (the Used bycolumn).modinfo xfs 2>/dev/null || modinfo ext4Inspect a filesystem module's metadata — note its depends:andparm:lines. Falls back toext4ifxfsisn't present.sysctl net.ipv4.ip_forwardRead a single tunable. Reading needs no root and changes nothing — this is how you verify a value took. ls /etc/sysctl.d/List the persistent tunable files. Anything here is reapplied at every boot — the durable half of the runtime-vs-persistent split.
- Build order is fixed:
make oldconfig->make -j$(nproc)->make modules_install->make install. Skipmodules_installand the new kernel boots without its drivers. modproberesolves dependencies viadepmod/modules.dep;insmodloads one.koblindly (anUnknown symbolerror means a missing dependencymodprobewould have loaded).- Inspect with
modinfo(metadata, params, deps — without loading) andlsmod(what's loaded and used by what). Persist module options and blacklists in/etc/modprobe.d/*.conf. sysctl -w(and writing/proc/sys/...) is runtime-only. Persist tunables in/etc/sysctl.d/*.confand apply withsysctl --system.
| Command | Effect | Persists across reboot? |
|---|---|---|
make modules_install | Copies .ko modules to /lib/modules/<ver>/, runs depmod | Yes (part of install) |
modprobe <name> | Loads a module + its dependencies | No (runtime) |
insmod <path.ko> | Loads one .ko file, no dependency resolution | No (runtime) |
modinfo <name> | Shows a module's metadata without loading it | Read-only |
lsmod | Lists currently loaded modules and their users | Read-only |
/etc/modprobe.d/*.conf | options/blacklist directives for modules | Yes |
sysctl -w key=val | Sets a tunable now, in memory only | No |
/etc/sysctl.d/*.conf + sysctl --system | Sets a tunable and reapplies at boot | Yes |
