![如何获取当前运行系统未使用的内核模块列表? (静态和加载)](https://linux22.com/image/189773/%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96%E5%BD%93%E5%89%8D%E8%BF%90%E8%A1%8C%E7%B3%BB%E7%BB%9F%E6%9C%AA%E4%BD%BF%E7%94%A8%E7%9A%84%E5%86%85%E6%A0%B8%E6%A8%A1%E5%9D%97%E5%88%97%E8%A1%A8%EF%BC%9F%20%EF%BC%88%E9%9D%99%E6%80%81%E5%92%8C%E5%8A%A0%E8%BD%BD%EF%BC%89.png)
有很多有趣的内核模块。感谢Linux内核,我现在知道有“乐高红外线塔”这样的东西。
我正在尝试将我的 Linux 内核精简到超出我显然不需要的范围。
为此,我需要一种编程方式来查找系统中当前未使用的内核模块。
我知道lsmod
,但这离我要找的还很远。
*** 相反的方法 - 消除法 ***
为了实现这个结果,我可能需要一种方法来确定当前哪些静态编译和加载的模块是正在使用。这些是菜单配置中通过“*”选择的,而不仅仅是“M”
我想我可能已经有办法“划掉”当前内核的 .config 文件中的每个模块,因为可以使用 grep 命令将模块名称映射到配置名称,如下所述:
...虽然我不确定这会持续多久。
所以我已经有了 .config 文件和内核源代码以及上面链接中的 grep 命令。瓶颈是静态使用和动态加载的内核模块的第一个列表。
这也许是一个“尽力而为”的问题。彻底清洁内核就像彻底清洁卧室一样困难。当我的卧室打扫干净时,到处还是有一些灰尘。这些与我对这个问题的答案的期望相同。
对于任何结果列表,都需要更多的手动过滤,因为我不认为我经常使用 DNS 名称解析之类的东西,尽管我确实间歇性地需要这些(具体来说,内核 DNS 解析实际上可能仅用于网络启动 -我不知道。)
必须有一种更快的方法来清理内核,而不是每隔几个小时重新编译一次内核,每次使用的模块越来越少。有更通用的策略吗?
答案1
我相信 -如何列出所有可加载的内核模块?是你问题的部分答案。
我编写了一个简单的 bash 脚本,它使用关联数组(因为它很快)来获取所有模块并确定是否加载了模块。代码是“小”垃圾。
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
要获取所有加载的模块,您可以使用:
bash x.sh | grep loaded
获取可用但未加载的模块 - 那就是大概回答你的问题:
bash x.sh | grep 'not used'
(...)
** 注意:此脚本不支持模块别名,因此只要在文件中找不到模块,就会出现“警告!...”消息。 **
编辑
要获取静态编译的模块,请使用
cat /lib/modules/$(uname -r)/modules.builtin
答案2
如果您只要求模块,答案会更简单一些,但是,由于您还要求静态编译功能,所以提供答案要困难得多。
对于动态加载的模块,尝试卸载它们然后检查输出可以帮助您,但是您需要记住,您当前未使用的即插即用设备(例如 USB 设备)需要某些模块。从长远来看,不编译模块会产生问题。此外,这种测试(卸载模块)可能会使您的系统崩溃,因此只有在您有测试安装的权限时才可以执行此操作。
对于静态加载的模块/函数,很难确定您是否需要某些东西,并且该过程与您的硬件密切相关,或者您是否需要支持特定功能的内核。您对此问题的选择无法由脚本处理。
不过,一个好的起点是获取启动过程日志的输出(某些发行版为 /var/log/boot.log)并检查内核消息:所需的大多数模块都会在日志中输出一些内容,然后您在进一步实验之前可以使用此列表作为“无接触”列表。