Configuring linux kernel
Configuring the Linux kernel is the first step when Compiling a Linux kernel. In this step you can specify what kind of computer components your kernel will support. Options of the Linux kernel cover architecture, device drivers, filesystems, networking, security and other settings.
Requirements
This document assumes you are running the latest 2.6 kernel, provided - as package - by your distribution. You can determine the kernel version with:
uname -r
If you do not have them, install the kernel sources; here assumed to be in /usr/src/linux.
Summary
This document will describe how to recognize config options for currently running- and not running modules. That information will be used to to (de)select those options for a configuration tailored for your computer. First will be described how options can be recognized and changed manually, below also is a script that parses the configuration of your distribution and deselects not loaded modules.
Manually
Rather than spoiling the kernel source directory we can build the kernel in a subdirectory of your home directory:
mkdir -p /home/$USER/build/kernel zcat /proc/config.gz > /home/$USER/build/kernel/.config
In the last command you extracted the .config file used to build the currently running kernel. This (hidden) .config file contains the kernel config options your distribution selected for this kernel, to support a wide range of hardware these options are mostly modules. This .config file will be loaded automatically by menuconfig.
cd /usr/src/linux make O=/home/$USER/build/kernel menuconfig
Instead of menuconfig, xconfig or gconfig will also work in a graphical environment.
The advantages of using the .config file of the distribution are:
- You know that the initial kernel configuration supports most hardware
- You can play safe by only deselecting the options you know you don't need
- Going through the options, you'll learn about the linux kernel, the computer and your hardware
The disadvantages:
- There are a LOT of options to be deselected
- You may not be certain about a lot of options
- Building the kernel with too many modules takes longer
While it is true that the build time of a kernel without unnecessary modules will be reduced, going through all config options will take much longer than the buildtime gained. On the other hand, you'll have to do this only once thoroughly, subsequent builds can use the same .config file.
When you exit and choose to save the options, the hidden .config file will be overwritten with the new choice of config options, and will be used when Compiling a Linux kernel. But before that, how to determine right options.
You can search for a config option in menuconfig. Press '/' and enter a config option (but strip CONFIG_). for instance 'USB_PRINTER', and it will list the current state (y/n/m), where to find this option in the menu and more.
Searching is is nice, however, only if you know the name of the config option and the state you'll need. So now is the question, how to get these. first the state:
- Notes
- Most options are about specifying whether you want a feature [*] compiled into the kernel image, [M] compiled as a module, or [ ] not compiled at all. Do not compile your hard drive and file system type as a module - these must be compiled in the kernel [*], e.g. " [*] ReiserFS".
- Here you to specify an enormous number of features. It is advisable to skim through all the sections to get a feel for the different things you can do. The kernel configuration is one LINUX program that offers lots of help--select < Help > on any feature. The raw help file is /usr/src/linux/Documentation/Configure.help can also be worth reading.
- When you're done with the config, click exit and save current configuration. Your file is now known as .config
Determine the wanted modules
To list all modules, type /sbin/modprobe -l
. To list loaded modules use /sbin/lsmod
. Note that the last list is much shorter.
In lsmod the first column lists the modules for hardware that was loaded during boot. It is very probable that you'll want these in your configuration too. If modules aren't loaded, it's an indication that you may not need them.
We'll need to have the same format like listed by modprobe to be able to determine the config option name later. Therefore we can cut the lsmod output and pipe it through modinfo:
#!/bin/bash /sbin/lsmod|cut -d" " -f1|xargs /sbin/modinfo -n;
Save as loaded_mods.sh and make it excecutable after editing by typing chmod u+x loaded_mods.sh
. You can then run it by typing ./loaded_mods.sh
Determine not wanted modules
Sometimes you want to know what modules you don't need. To list those enter as root in the console:
#!/bin/bash modprobe -l | grep -v -E "^($(lsmod | cut -d" " -f1 | tail +2 | xargs modinfo -n | tr "\n" "|"))$"
save as not_loaded_mods.sh and type chmod u+x not_loaded_mods.sh
Module names to config options
Now we know how to determine the wanted state for modules, it's time to learn how to translate the module name into a config option. We can do this by parsing makefiles in kernel source (sub)directories. In the makefiles the config options and module names are listed.
#!/bin/bash mod="${1%.ko}"; dir="${1%/*}"; sed -e :a -e '/\\$/N; s/\\\n//; ta' "${dir#*/kernel/}/Makefile" | \ sed -n "s/^obj-\$(CONFIG_\([A-Z0-9_]*\))\W*+=\W*"${mod##*/}"\.o$/\1/p";
Save as mod2config.sh and make it excecutable. This script will need an module (as listed in modprobe -l) and will translate it into a config option. So to list all not loaded modules:
for f in `./not_loaded_mods.sh`; do ./mod2config.sh $f; done | less
and for the loaded:
for f in `./loaded_mods.sh`; do ./mod2config.sh $f; done | less
Conclusion
Using this information, you can search for config options in menuconfig and activate or deactivate them. Please use some common sense, however. Only deactivate a module if you cannot think of a use for the module. Also there are options that were not modules in the original .config. You'll have to figure the required settings for these for yourself.
As a script
You don't have to be root to run the script below, but you should be running a 2.6 kernel. It parses that kernels' .config and removes modules when not currently loaded. You may want to add some modules you'll need occasionally after running this script.
mkdir -p /home/$USER/build/kernel/ cd /home/$USER/build/kernel/
save this script debloatconfig in this directory
#!/bin/bash # Copyright (c) 2007 Roel Kluin GNU GPL v.2 appvers="0.2" usage() { cat << ENDUSAGE suggest a kernel .config based on running modules in a highly modular kernel usage: kcnfsuggest [options] -c|--config FILE specify the kernel config file -l|--list FILE use kernel config-module list, created with make_kcfg-modlist -k|--kernel-source DIRECTORY specify the kernel source directory -y|--yes If a module is loaded suggest to compile it in (this may not always be possible) -m|--modules If a module is loaded suggest to compile it as a module (default) -K|--keep-modules If not loaded now, suggest to keep it as a module -n|--no If not loaded now, suggest to not compile it (default) -C|--comment TEXT Display \"text\" after each line modified. In comment, where needed \"# \" is placed before the text -h|--help Prints this message -v|--version print version and exit" ENDUSAGE } get_mod2conf_makefile() { sed -n "s/^\W*obj-\$(CONFIG_\([A-Z0-9_]*\))\W*+=.*$1\.o.*$/\1/p" "$2/Makefile"; } set_config_for() { if [ "$2" = "y" ]; then echo "$1=y${ym_comment}"; elif [ "$2" = "m" ]; then echo "$1=m${ym_comment}"; else echo "# $1 is not set${n_comment}"; fi } OPTS=`getopt -o hvl:k:ymnKc:C: --long help,version,list,kernel-source:yes,modules,keep-modules,no,keep-modules,config:,comment: -n kcnfsuggest -- "$@"` || exit 1; eval set -- "$OPTS"; # default values loaded_module="m"; not_loaded_module="n"; ksrcdir="/usr/src/linux-`uname -r`/"; while true ; do case "$1" in -h|--help) usage; exit 0 ;; -c|--config) cfgfile="$2"; shift 2;; -l|--list) list="$2"; shift 2;; -k|--kernel-source) ksrcdir="$2"; shift 2;; -y|--yes) loaded_module="y"; shift ;; -m|--modules) loaded_module="m"; shift ;; -n|--no) not_loaded_module="n"; shift ;; -C|--comment) ym_comment=" # $2"; n_comment=" $2"; shift 2;; -K|--keep-modules) not_loaded_module="m"; shift ;; -v|--version) echo "version $appvers"; exit 0 ;; --) shift ; break ;; *) usage ; exit 1 ;; esac done if [ -z "$list" ]; then if [ ! -d "$ksrcdir" ]; then echo "Specify a kernel source directory or a config-module list" 1>&2; usage; exit 1; fi # try to guess the .config location if [ -z "$cfgfile" ]; then if [ -r "${ksrcdir}config.generic" ]; then cfgfile="${ksrcdir}config.generic"; elif [ -r "${ksrcdir}.config" ]; then cfgfile="${ksrcdir}.config"; fi fi elif [ ! -r "$list" ]; then echo "ERROR: List could not read: $list" 1>&2; exit 1; fi if [ -z "$cfgfile" ]; then echo "Please specify a config file to parse" 1>&2; usage; exit 1 elif [ ! -r "$cfgfile" ]; then echo "ERROR: The config file cannot be read: $cfgfile" 1>&2; exit 1 fi mi="`whereis modinfo | cut -d" " -f 2`"; if [ "$mi" == "modinfo:" ]; then echo "modinfo not found" 1>&2; fi for module in `cat /proc/modules|cut -d" " -f1`; do license="`$mi -l "$module"`"; if [ -n "${license##*GPL*}" ]; then echo "WARNING: $module has licence \"$license\", when built this \ kernel will not include proprietary modules" 1>&2; else module="`$mi -n $module`"; dir="${module%/*}"; if [ -n "${dir##*/kernel/*}" ]; then echo "WARNING: module not in kernel directory: $module" 1>&2; continue; fi mod="${module%.ko}"; mod="${mod##*/}" if [ -z "$list" ]; then dir="${ksrcdir}${dir#*/kernel/}"; option="`get_mod2conf_makefile $mod $dir`"; else option="`grep ":$mod$" $list`"; option="${option%:*}"; fi if [ -z "$option" ]; then echo "WARNING: no kernel config option found for $mod" 1>&2; else # loop because grep/sed may have returned more options for op in $option; do char_count=${#enable_option}; enable_option="${enable_option/ $op /}"; if [ $char_count -ne ${#enable_option} ]; then # echo "WARNING: duplicate option ignored: $op, for $mod" 1>&2; continue; fi enable_option="$enable_option $op"; done fi fi done for line in `cat "$cfgfile"|tr " " "^"`; do option=${line##\#*}; # delete comment option=${option%=m*}; option=${option%%*=*}; # delete non-module options if [ "${option#CONFIG_}" ]; then char_count=${#enable_option}; enable_option="${enable_option/$option/}"; if [ $char_count -eq ${#enable_option} ]; then set_config_for "$option" "$not_loaded_module"; else set_config_for "$option" "$loaded_module"; fi else # other options (non-module or not recognized) are left unchanged echo "${line//^/ }"; fi done
now run:
chmod u+x debloatconfig zcat /proc/config.gz > std.config
If the latter command didn't work, then the kernel you run lacks the CONFIG_IKCONFIG option. You may be able to find the .config from some other source.
debloatconfig -c std.config -k /usr/src/linux/ -m -C "changed by $USER" > .config
you may see some warnings if you have proprietary modules, or if a module wasn't found. In the latter case the generic configuration won't be changed.
cd /usr/src/linux make O=/home/$USER/build/kernel/ oldconfig
if you want to upgrade to a newer kernel, go to the path of that kernel's sources and do again:
make O=/home/$USER/build/kernel/ oldconfig
If source code was changed, between kernel versions, the state for the corresponding config options will be asked again.
finally, I still suggest you use this to review the settings:
make O=/home/$USER/build/kernel/ menuconfig
There are a few reasons why I'd suggest you to review the settings after usage, however:
- Compiled in options won't be changed, although changing them may benefit your hardware.
- This script removes modules that are not loaded. This may include some modules you'll want to use occasionally.
- resolve warnings
The advantage is, that now you'll have to make much less changes.
Other helpful tools
- How to build and install your own Linux kernel
- Documentation of your hardware (sometimes available online)
- Documentation directory in your kernel sources
cat /proc/cpuinfo
lspci
- Help options in menuconfig