L20: Configuring the Linux Kernel

 

CHAPTER 2  ·  PART 2  ·  LINUX KERNEL PROGRAMMING

Configuring the Linux Kernel

Master make menuconfig — understand kernel config options, tristate states, CONFIG_IKCONFIG, CONFIG_LOCALVERSION, and the .config file — all in one free tutorial

Linux 6.x
Verified on
Beginner
Level
~20 min
Read Time
Free
No signup

Topics Covered

make menuconfig
Kernel tristate options
CONFIG_IKCONFIG
CONFIG_LOCALVERSION
make localmodconfig
.config file
/proc/config.gz
Kernel build system
General Setup menu
Linux 6.x

What You Will Learn

  • How to read and understand a kernel configuration change table
  • The difference between y, m, and n in kernel config (the tristate system)
  • How to navigate and use make menuconfig step by step
  • What CONFIG_IKCONFIG and CONFIG_IKCONFIG_PROC do and why you should enable them
  • How to tag your custom kernel with CONFIG_LOCALVERSION
  • How to search for any config option inside menuconfig using the / key
  • How the final .config file connects your choices to the kernel build

Why Kernel Configuration Matters

📷 Image Suggestion

Insert a screenshot of a real terminal showing make menuconfig running — the blue ncurses UI with menu items visible. Caption: “The make menuconfig interface running on Linux 6.x — your control panel for the kernel”. Alt text: make menuconfig terminal interface Linux kernel configuration.

The Linux kernel is not a single fixed binary. It is a highly configurable piece of software with thousands of optional features — device drivers, filesystems, security mechanisms, debugging tools, power management options, and more. You choose what goes in and what stays out before you compile it.

This selection process is called kernel configuration. Before building any custom kernel, you must produce a .config file that records every single choice. The tool that helps you create and edit this file through a friendly menu interface is make menuconfig.

Think of it this way: the kernel source code is a warehouse full of features. menuconfig is the order form. The .config file is your filled-out order. And make is the factory that actually builds what you ordered.

The Three States of a Kernel Config Option

Every kernel feature supports one of three states. The kernel build system calls this the tristate system. When you look at menuconfig, you will see symbols on the left of each menu item. Those symbols tell you the current state.

Kernel Config Tristate System — How Each State Affects Your Build
Symbol Value What It Means Build Result
<*> y (yes) Built into the kernel image Always present from boot. No module needed.
<M> m (module) Built as a loadable kernel module A .ko file. Load with modprobe when needed.
< > n (no) Feature is excluded entirely No code compiled. Smallest kernel size.

When tutorials write a config change like n -> m, it means: take this option from disabled and enable it as a module. When you see m -> y, it means change from module to built-in (always on). The spacebar cycles through these states inside menuconfig.

Boolean Options vs Tristate Options — Quick Reference
Type Symbols You See Possible Values Example
Boolean [*]   or   [ ] Only on (y) or off (n) SMP support, PREEMPT
Tristate <*>, <M>, < > y, m, or n CONFIG_IKCONFIG, most drivers

How to Read a Kernel Config Change Table

Kernel programming books and tutorials often list configuration changes in a 4-column table. Once you know what each column means, these tables are very easy to follow. Here is a breakdown:

Anatomy of a Kernel Config Change Table — 4 Columns Explained
Column What It Tells You Example Value
1 — Purpose Why you are making this change — what it enables or configures Enable Kernel .config support
2 — Menu Path Where to find it in menuconfig — written as Parent / Child General Setup / Kernel .config support
3 — CONFIG Name The actual symbol name. Searchable in menuconfig with / CONFIG_IKCONFIG
4 — Value Change Written as old -> new. Shows exactly what to change it to m -> y   or   (none) -> -mydev

The third column is especially useful: whenever you are lost in the menus, just press / inside menuconfig and type the CONFIG symbol name. You will be taken directly to it.

💡 Pro Tip: The / Search Key is Your Best Friend

Inside menuconfig, press / and type a CONFIG symbol like IKCONFIG. menuconfig instantly shows you the full menu path, the current value, and any dependencies. This works across all kernel versions — even when menu positions change between releases.

Step-by-Step: Configuring the Kernel with make menuconfig

📷 Image Suggestion

Insert a screenshot of the General Setup submenu inside menuconfig, with “Kernel .config support” highlighted. Alt text: menuconfig General Setup Kernel .config support highlighted. Caption: “Navigating to Kernel .config support inside the General Setup submenu of make menuconfig”.

Let us walk through a complete, real example. We will configure Kernel .config support — a highly practical option that embeds your build configuration directly inside the kernel image. Here are all the steps from scratch:

menuconfig Configuration Workflow — 8 Steps at a Glance
Step Action Command or Key
1 Go to kernel source directory cd /path/to/linux-source
2 Generate a lean starting config make LSMOD=... localmodconfig
3 Launch the menu UI make menuconfig
4 Enter General Setup submenu Arrow keys + Enter
5 Highlight Kernel .config support Down arrow / or use / search
6 Read the help text (optional) Right arrow to Help → Enter
7 Toggle option to built-in (<*>) Spacebar
8 Save and exit Esc Esc → Save → Exit

Now let us look at each step in detail with the actual commands:

Step 1 — Go to the Kernel Source Directory

Navigate to the root of your Linux kernel source tree. This is wherever you extracted or cloned the kernel source.

cd /path/to/linux-source

Verify you are in the right place — you should see files like Makefile, Kconfig, and directories like arch/, drivers/, init/.

Step 2 — Create a Starting Config with localmodconfig

Rather than starting from a huge distribution config with thousands of options, use localmodconfig to create a lean starting point based on what your current system actually uses.

lsmod > /tmp/lsmod.now
make LSMOD=/tmp/lsmod.now localmodconfig

lsmod lists all kernel modules currently loaded. Piping that list into localmodconfig tells the build system: only enable the modules this machine is actually using. The result is a much smaller .config and much faster build times compared to a full distribution config.

Step 3 — Launch menuconfig

make menuconfig

This opens the ncurses-based full-screen menu in your terminal. It reads your current .config and displays all options. Use arrow keys to move, Enter to select or enter a submenu, Esc to go back, and Spacebar to toggle options.

Step 4 — Enter General Setup

On the main menu, use the down arrow to highlight General Setup and press Enter. This is usually near the top of the list on x86-64 systems. All the basic kernel identity and behavior options are in here.

Step 5 — Find “Kernel .config support”

Inside General Setup, scroll down using the down arrow. You are looking for an item that says:

<M> Kernel .config support

The <M> prefix means it is currently set as a module. If you cannot find it by scrolling, press / and type IKCONFIG to jump to it directly.

Step 6 — Read the Help Text

With the item highlighted, press the right arrow key until the bottom toolbar cursor is on < Help >, then press Enter. The help screen for CONFIG_IKCONFIG explains exactly what it does and what the sub-options mean. This is a good habit to build — many config options have very informative help text. Press Enter on < Exit > when done.

Step 7 — Toggle to Built-In Using Spacebar

Press Spacebar once. The display changes from:

<M> Kernel .config support

to:

<*> Kernel .config support
[ ]   Enable access to .config through /proc/config.gz (NEW)

The <*> means this feature is now baked directly into the kernel image — always on, no module loading needed. A new child option also appeared: Enable access to .config through /proc/config.gz. Toggle this on too with Spacebar if you want to read the config from a running kernel.

Step 8 — Save and Exit

Press Esc twice to go back to the main menu. Navigate right with the arrow key to highlight < Save > and press Enter to save. Then select < Exit >. Your choices are now written to the .config file in the kernel source root.

Understanding CONFIG_IKCONFIG and CONFIG_IKCONFIG_PROC

📷 Image Suggestion

A terminal screenshot showing zcat /proc/config.gz | grep IKCONFIG output on a running Linux system, proving that the config is accessible. Alt text: reading kernel config from /proc/config.gz on running Linux system.

CONFIG_IKCONFIG and CONFIG_IKCONFIG_PROC — What Each Option Does
Config Option What It Does How to Access the Config
CONFIG_IKCONFIG=y Embeds a compressed copy of .config inside the kernel binary itself. Recoverable even without the original source tree. scripts/extract-ikconfig vmlinuz
CONFIG_IKCONFIG_PROC=y Sub-option of IKCONFIG. Exposes the config through /proc/config.gz on any running kernel that was built with this option. zcat /proc/config.gz
CONFIG_IKCONFIG=m Builds config support as a loadable module. You must load it before accessing config data. modprobe configs first

Here is how to check the kernel config on any running Linux system — even one you did not build yourself:

# Try /proc/config.gz first (fastest — works if IKCONFIG_PROC=y)
zcat /proc/config.gz | head -30

# Most distributions ship the config in /boot
cat /boot/config-$(uname -r) | grep IKCONFIG

# Extract from the kernel binary (works if IKCONFIG=y was set)
scripts/extract-ikconfig /boot/vmlinuz-$(uname -r) | head -30

Enabling CONFIG_IKCONFIG=y is considered a best practice for any development or production kernel. The memory overhead is tiny and the benefit — always being able to inspect how a kernel was built — is enormous.

CONFIG_LOCALVERSION — Give Your Custom Kernel a Name

When you run uname -r, Linux prints the kernel release string. For a distribution kernel this might look like 6.8.0-45-generic. When you build a custom kernel, that string will just say something like 6.8.0 — with no hint that it is your custom build.

CONFIG_LOCALVERSION lets you append a custom suffix to this string. This is simple but extremely practical — it helps you instantly tell which kernel is running when you have multiple builds deployed.

CONFIG_LOCALVERSION — Effect on uname -r Output
Scenario CONFIG_LOCALVERSION value uname -r output
No custom string set (none) 6.8.0
Development build -dev01 6.8.0-dev01
Embedded product build -embedded-v3 6.8.0-embedded-v3
Real-time patched kernel -rt-preempt 6.8.0-rt-preempt

To set it: in menuconfig go to General Setup → Local version – append to kernel release. Press Enter, type your string (starting with a hyphen is conventional), and confirm. The config symbol is CONFIG_LOCALVERSION.

menuconfig Keyboard Shortcuts — Complete Reference

📷 Image Suggestion

A clean annotated diagram or screenshot of the menuconfig bottom toolbar showing the Save, Load, Help, and Exit buttons highlighted. Alt text: menuconfig toolbar buttons keyboard shortcuts Linux kernel.

make menuconfig — All Keyboard Shortcuts You Need
Key Action When to Use
Arrow Keys Move up, down, left, right in menu Navigation
Enter Enter a submenu or activate a button Drill into menus
Spacebar Toggle config state: y → m → n → y Changing option values
/ (slash) Open search — find any CONFIG by name Finding options quickly
Y Set highlighted option to built-in (y) Quick set to yes
M Set highlighted option to module (m) Quick set to module
N Set highlighted option to disabled (n) Quick set to no
? or H Show help text for the highlighted option Understand what an option does
Esc Esc Go back one level (exit current submenu) Going up in menu tree

How the .config File Connects to Your Kernel Build

After you finish in menuconfig, your selections are written to a file called .config in the kernel source root. This file is the bridge between your choices and the actual kernel binary. Understanding what is inside it helps you debug build issues and verify your configuration.

From menuconfig Choices to Bootable Kernel — The Full Flow
Your Choices
via menuconfig
.config file
kernel source root
make bzImage
compilation
Custom Kernel
bootable image

Here is what the .config file looks like inside — it is plain text:

#
# Automatically generated by make menuconfig
#
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOCALVERSION="-dev01"
# CONFIG_SWAP is not set
CONFIG_MODULES=y

Lines starting with # and ending with is not set are disabled options. Lines with =y are built-in. Lines with =m are modules. String values use quotes. This file is readable and editable directly, but using menuconfig is safer because it enforces dependencies automatically.

.config File — Three Line Formats Explained
Line Format Meaning Example
CONFIG_X=y Feature compiled into kernel (built-in) CONFIG_IKCONFIG=y
CONFIG_X=m Feature compiled as loadable module CONFIG_EXT4_FS=m
# CONFIG_X is not set Feature is disabled — no code compiled # CONFIG_SWAP is not set
CONFIG_X=”string” String value (name, version suffix, etc.) CONFIG_LOCALVERSION=”-dev”

Linux 6.x Notes — What Changed and What Did Not

These are confirmed unchanged in Linux 6.x:

  • CONFIG_IKCONFIG and CONFIG_IKCONFIG_PROC exist and behave identically
  • CONFIG_LOCALVERSION still lives under General Setup
  • make menuconfig navigation and keyboard shortcuts are the same
  • The / search key works identically across all kernel versions
  • The .config file format has not changed

What to watch for: Menu positions of some options shift slightly between kernel releases as new options are added. If an option is not where you expect it, use / and the CONFIG symbol name — that always works. Also, when migrating a .config between kernel versions, always run make oldconfig or make olddefconfig to handle new config symbols that appeared in the newer kernel.

Frequently Asked Questions

What is make menuconfig and why do I need it?

make menuconfig is the standard interactive tool for configuring the Linux kernel before building it. It reads all the kernel’s Kconfig files and presents the options as a navigable menu. You need it because the Linux kernel has thousands of configuration options and you must produce a .config file before compilation. Without a valid .config, the build will either fail or use defaults that may not suit your hardware or use case.

Is there a difference between make menuconfig and make xconfig?

They configure the same options but use different interfaces. make menuconfig uses a text-based ncurses UI that runs in any terminal — this is the most widely used option for server and embedded development. make xconfig opens a Qt-based graphical window and requires a desktop environment. make nconfig is another text-based alternative with a slightly different look. All three read and write the same .config file.

Can I edit the .config file manually instead of using menuconfig?

Technically yes, but it is risky. The .config file is plain text and human-readable, so you can open it in any text editor. However, many kernel options have dependencies — enabling option A may require option B to also be enabled. menuconfig enforces these dependencies automatically. If you edit .config manually and break a dependency, the build may fail with cryptic errors. If you do edit manually, always run make oldconfig afterwards to validate and fix the dependency chain.

What happens if I run make without a .config file?

The build will fail with an error saying the configuration is missing. On some kernel versions it may ask you interactively about each option (like make config). The safe approach is to always generate a starting .config first — either with make localmodconfig, make defconfig, or by copying your distribution’s config from /boot/config-$(uname -r).

What does n -> m mean in a kernel config change table?

It means: change this config option from its current value of n (disabled/not compiled) to m (built as a loadable kernel module). So if a tutorial says a config change is n -> m, open menuconfig, find that option, and press Spacebar until it shows <M>.

How do I upgrade my .config when moving to a newer kernel version?

Run make oldconfig in the new kernel source directory with your old .config copied to it. This command reads all existing settings from the old file and then asks you interactively only about the new config symbols introduced in the new kernel version. If you want to skip the questions and just accept the defaults, run make olddefconfig instead.

Does enabling CONFIG_IKCONFIG make my kernel significantly larger?

No. The .config data is stored compressed inside the kernel image. For a typical configuration the size increase is around 10–30 KB — negligible in practice. The benefit of always being able to recover the exact build configuration far outweighs this tiny overhead. This is why most embedded and production teams enable it.

Interview Questions and Answers

Q1: What is the difference between CONFIG_IKCONFIG=y and CONFIG_IKCONFIG=m?

When set to y, the kernel configuration data is embedded directly into the kernel binary itself using the IKCFG_ST / IKCFG_ED markers. It is always accessible without loading anything. When set to m, the same data is packaged into a kernel module called configs.ko. You must first run modprobe configs before /proc/config.gz becomes available. For embedded systems and production kernels, y is preferred because it removes the dependency on module loading.

Q2: A running Linux system has no .config file in /boot. How do you find out what options it was built with?

There are three approaches in order of preference. First, check if /proc/config.gz exists — if yes, CONFIG_IKCONFIG_PROC=y was set and you can run zcat /proc/config.gz to read the full config. Second, use the scripts/extract-ikconfig script on the kernel binary in /boot/vmlinuz-$(uname -r) — this works if CONFIG_IKCONFIG=y was set. Third, if neither works, the kernel was built without IKCONFIG — you can only infer the config by inspecting loaded modules with lsmod and checking /sys/module/.

Q3: What does make localmodconfig do and why is it better than make defconfig for a development machine?

make localmodconfig takes the list of kernel modules currently active on the running system (from lsmod) and generates a .config that enables only those modules. make defconfig on the other hand generates a generic configuration with broad hardware support — resulting in hundreds of unnecessary drivers being compiled. For a development machine, localmodconfig produces a kernel that compiles in a fraction of the time (sometimes 10x faster) because only the modules actually needed by that specific machine are included.

Q4: What is the purpose of CONFIG_LOCALVERSION and where is it set?

CONFIG_LOCALVERSION appends a custom string to the kernel release version shown by uname -r. It is set in menuconfig under General Setup → Local version – append to kernel release. This is extremely useful when multiple custom kernels are deployed — the suffix immediately identifies which build is running. Common patterns include -dev01, -embedded-v2, or -rt for real-time patched kernels.

Q5: How does the kernel’s build system use the .config file?

The .config file is processed by the kernel’s Kbuild system. It is converted into a C header file called include/generated/autoconf.h which contains #define macros for every enabled option. Every C source file in the kernel can then use #ifdef CONFIG_X to conditionally compile code for that feature. Options set to m cause separate object files to be produced and packaged into loadable .ko module files.

Q6: Why might running make on a new kernel version with an old .config file fail or produce a broken kernel?

New kernel releases often introduce new config symbols that do not exist in the old .config. If the build system encounters an unknown symbol, it may assign an unpredictable default. More critically, renamed symbols may silently disable features that were previously enabled. The correct fix is to run make oldconfig which explicitly prompts you for each new symbol, or make olddefconfig which accepts defaults for all new symbols automatically without prompting.

What Is Next in This Series?

Your kernel is now configured. In the next part we will actually compile it, install the modules, update the bootloader, and boot into your custom Linux kernel for the first time.

→ Previous Lecture
← Next Lecture

EmbeddedPathashala.com  ·  Free Linux Kernel Development Course  ·  Verified on Linux 6.x  ·  No signup required

 

Leave a Reply

Your email address will not be published. Required fields are marked *