3

There are a lot of interesting kernel modules. Thanks to the Linux kernel, I now know there is such a thing as a “Lego Infrared Tower”.

I’m trying to slim down my Linux kernel beyond the point of things I obviously don't need.

To do this, I need a programmatic way to find the unused kernel modules currently in my system.

I know about lsmod, but that’s very far away from what I’m looking for.

*** The reverse approach - by elimination ***

What I might need in order to achieve this result is a way to determine which statically compiled and loaded modules currently are in use. These are the ones selected by “*” in the menuconfig and not just “M”

I think I already might have a way to “cross out” each of those modules in the .config file of the current kernel, because it is possible to map module names to config names using a grep command as described here:

Binding lsmod module name with kernel configuration menu entry

... though I am not sure how consistently that will work.

So what I have already is the .config file and the kernel sources and that grep command from that link above. The bottleneck is the first list of statically-used and dynamically-loaded kernel modules.

This is perhaps a “best effort” question. It is as difficult to completely clean a kernel as it is to completely clean a bedroom. When my bedroom is clean, there is still some dust here and there. These are the same expectations I would expect for an answer to this question.

With any resulting list, more manual filtering will be needed, because I don't think I am constantly using things like DNS name resolutions, though I do need those intermittently (specifically, kernel DNS resolutions may actually be used for network boot only -- I am not sure.)

There has to be a faster way to clean a kernel than recompiling the kernel every few hours with fewer and fewer modules each time. Is there a more common strategy?

1
  • Doesn't lsmod list the modules used right now by the kernel? Most are auto-loaded when needed so there is your list? Of course, those parts of the kernel that are compiled in but could in theory be a module (if you configure them as "M" not "Y") are not modules and are therefore not listed by lsmod.
    – Ned64
    Mar 28, 2021 at 21:34

2 Answers 2

3
+50

I believe that - How to list all loadable kernel modules? is a partial answer to your question.

I wrote a simple bash script, that uses an associative array (because it's fast) to get all modules and determine if a module is loaded. Code is "little" trashy.



declare -A all_modules # 0 module is used 1 module is not used

#
# Note when ls shows module some modules have names separated by `_`
# In the very same time files that contains this modules might have `-`
# Example:
# /usr/lib/modules/5.11.9-200.fc33.x86_64/kernel/arch/x86/crypto/ghash-clmulni-intel.ko.xz - file
# [Alex@NormandySR2 i686]$ lsmod | grep 'ghash' 
# ghash_clmulni_intel    16384  0
# At the very same time, I didn't find any module that has `-` reported by lsmod
# [Alex@NormandySR2 i686]$ lsmod |grep '-'


# I know that for and find is fragile, but it's the simplest way
for i in $(find /lib/modules/$(uname -r) -type f -name '*.ko*'); do 
    module_name=$(basename $i);
    # used {module_name%.*}, but cut with is simpler, and works with multiple extensions like .ko.xz
    module_without_extension=$(echo $module_name | cut -f 1 -d '.')
    # replace - with _ 
    module_name_normalized=$(echo $module_without_extension | sed 's/-/_/g')
    all_modules[$module_name_normalized]=1
done

# Note that `lsmod` output starts with "Module Size Used By " that's why sed is used
IFS=$'\n'
for i in $(lsmod | sed '1d;$d'); do 
    module_name=$(echo $i | awk '{print $1}')
    echo "$module_name"
    # check module from lsmod is in all modules
    if [[ -v all_modules[$module_name] ]]; then
        all_modules[$module_name]=0
    else
        echo "Warning! There is no $module_name module in all_modules array - adding it to all modules but you should check"
        all_modules[$module_name]=0
    fi
done

# print output
for i in "${!all_modules[@]}"
do
  if [ ${all_modules[$i]} -eq 0 ]; then
      echo "$i is loaded"
  else
      echo "$i is not used"
  fi
done

To get all loaded modules, you might use:

bash x.sh  | grep loaded

To get modules that are available but not loaded - and that is probably answer to your question:

bash x.sh  | grep 'not used'
(...)

** Note: This script does not support module aliases, so there is a "Warning! ..." message whenever the module is not found in files. **

Edit

To get statically compiled modules use

cat /lib/modules/$(uname -r)/modules.builtin
3
  • This is a partial answer because it doesnt determine the “statically compiled” modules in use / not-use. Staticaly compiled modules are the modules that are marked with a “*” in the menuconfig command Mar 30, 2021 at 16:01
  • 1
    @steveantwan fixed. Mar 30, 2021 at 22:48
  • When checking your answer, i found the same answer here: superuser.com/questions/577307/… Apr 5, 2021 at 15:57
1

If you were asking only for modules, the answer would be a bit simpler, but, as you are also asking for statically compiled functionality, it is much harder to provide an answer.

For dynamically loaded modules, trying to unload them and then checking the output can help you, however you need to remember that some modules are needed for plug-n-play devices, such as USB devices, that you are not currently using. Not compiling the modules will create problems in the long run. In addition, this kind of test (unloading modules) can crash your system, so only do it if you have permission to test your installation.

For statically loaded modules/functions, it is much harder to figure out if you need something, and the process is very much linked to your hardware, or whether you want a kernel that supports specific features. Your choice for this question cannot be handled by a script.

A good starting point though is to get the output of the boot process log, (/var/log/boot.log for some distros) and check the kernel messages: most of the modules that are needed will output something in the logs and you can use this list as a "no-touch" list before further experimentation.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .