Linux内核与模块管理:uname、lsmod、modprobe、sysct

Linux内核与模块管理:uname、lsmod、modprobe、sysctl

内核是 Linux 的心脏,但日常打交道最多的其实是两件事:看版本(uname)、管理模块和参数(lsmod、modprobe、sysctl)。装网卡驱动、开 IP 转发、调文件句柄上限,都落在这几条命令上。这一篇把它们串起来。

一、uname:看内核与系统信息

语法格式

bash 复制代码
uname [选项]

常用参数

参数 说明
-a 全部信息:内核名、主机名、版本、架构
-r 只看内核版本号
-m 机器硬件架构(x86_64、aarch64)
-n 主机名
-v 内核编译日期

示例与预期输出

bash 复制代码
uname -a

预期输出:

text 复制代码
Linux web01 6.8.0-45-generic #45~22.04.1-Ubuntu SMP Wed Sep 4 13:02:00 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

拆一下 6.8.0-45-generic:主版本 6、次版本 8、修订 0、发行版补丁 45、generic 是 Ubuntu 的通用内核变体。这个版本号后面找模块路径时天天用。

bash 复制代码
uname -r

预期输出:

text 复制代码
6.8.0-45-generic

模块都装在 /lib/modules/$(uname -r)/ 下面。升级内核后旧模块路径还在但不会再被加载,uname -r 一变,整套模块树就换了。

二、lsmod:看已经加载的模块

Linux 内核把驱动做成可插拔模块,需要时装进来,不需要时卸掉。lsmod 列出当前已经在内核里的模块。

语法格式

bash 复制代码
lsmod

它本质是读 /proc/modules,没有选项。

示例与预期输出

bash 复制代码
lsmod

预期输出(节选):

text 复制代码
Module                  Size  Used by
e1000e               413696  0
ixgbe                307200  0
xt_conntrack          16384  1
nf_conntrack         155648  1 xt_conntrack
sd_mod                57344  3
usbcore              311296  4 xhci_hcd,usb_storage

三列含义:模块名、占用内存大小、被多少其他模块/进程引用。最后一列是引用它的模块。Used by 那列不是 0,说明还有东西在用,这时候想卸载会失败------后面讲 modprobe -r 时细说。

想知道某个驱动对应哪个模块,用 modinfo:

bash 复制代码
modinfo e1000e

预期输出(节选):

text 复制代码
filename:       /lib/modules/6.8.0-45-generic/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko
version:        6.8.0
license:        GPL
description:    Intel(R) PRO/1000 Network Driver
author:         Intel Corporation
alias:          pci:v00008086d000015A3sv*sd*bc*sc*i*

filename 告诉你模块文件在硬盘哪。alias 是 PCI 设备 ID 匹配规则,内核发现对应硬件时自动按 alias 找到这个模块。

三、modprobe:加载与卸载模块

语法格式

bash 复制代码
modprobe [选项] 模块名

不带选项就是加载。modprobe 比 insmod 强在自动处理依赖:它读 /lib/modules/$(uname -r)/modules.dep,把这个模块依赖的其他模块一起拉进来。

常用参数

参数 说明
(无) 加载模块
-r 卸载模块(同时卸载没人再用的依赖)
-n 干跑,不真执行,看会发生什么
-v 显示详细动作

示例与预期输出

加载一个模块:

bash 复制代码
sudo modprobe e1000e

没报错就是成了。验证:

bash 复制代码
lsmod | grep e1000e

预期输出:

text 复制代码
e1000e               413696  0

卸载:

bash 复制代码
sudo modprobe -r e1000e

如果这张网卡还在用、有 IP 地址,内核会拒绝卸载,报 Module e1000e is in use。先把网卡 down 掉再卸。

对比一下 insmod:它只往内核塞指定那一个 .ko 文件,不处理依赖。实际工作几乎都用 modprobe,insmod 留着自己写模块调试时用。

开机自动加载模块

希望每次开机都加载某模块,写进配置:

bash 复制代码
echo "e1000e" | sudo tee /etc/modules-load.d/network.conf

/etc/modules-load.d/ 下任意 .conf 文件里一行一个模块名,开机时 systemd-modules-load.service 会读。Debian 老版本用 /etc/modules,新发行版统一走 modules-load.d。

给模块传参数

有些模块需要启动参数,比如某个声卡要指定缓冲区大小。在 /etc/modprobe.d/ 下写:

text 复制代码
options snd_hda_intel index=0

文件名随便,.conf 后缀。modprobe snd_hda_intel 时会自动带上 index=0。

四、sysctl:运行时改内核参数

内核暴露了几千个可调参数,绝大多数挂在 /proc/sys/ 下。sysctl 是官方接口。

语法格式

bash 复制代码
sysctl [选项] [参数=值]

常用参数

命令 说明
sysctl -a 列出所有可调参数和当前值
sysctl 键名 查单个参数
sysctl -w 键名=值 运行时立即改
sysctl -p 从配置文件重新加载
sysctl --system 加载所有默认配置目录

示例与预期输出

查 IP 转发开没开:

bash 复制代码
sysctl net.ipv4.ip_forward

预期输出:

text 复制代码
net.ipv4.ip_forward = 0

0 是没开。当路由器、跑 Docker、做 k8s 节点都得开成 1。

临时开(重启失效):

bash 复制代码
sudo sysctl -w net.ipv4.ip_forward=1

预期输出:

text 复制代码
net.ipv4.ip_forward = 1

永久生效写配置。Ubuntu 上建议写到 /etc/sysctl.d/99-custom.conf,别直接改 /etc/sysctl.conf:

text 复制代码
net.ipv4.ip_forward = 1
vm.swappiness = 10

加载:

bash 复制代码
sudo sysctl -p /etc/sysctl.d/99-custom.conf

swappiness=10 的意思是内存还够的时候尽量别用 swap,数据库机器常用这个调优。

/proc/sys/ 路径和 sysctl 键名是一一对应的,把点换斜杠、去掉前缀:

sysctl 键名 对应文件
net.ipv4.ip_forward /proc/sys/net/ipv4/ip_forward
vm.swappiness /proc/sys/vm/swappiness
kernel.hostname /proc/sys/kernel/hostname

不想用 sysctl,直接 echo 1 > /proc/sys/net/ipv4/ip_forward 效果一样,重启都失效。

几个高频调参项,搞网络和数据库的人常打交道:

键名 默认 生产常用 用途
net.ipv4.ip_forward 0 1 开启内核转发,Docker/路由器必开
vm.swappiness 60 10 越小越倾向用物理内存,数据库建议调低
fs.file-max 随内存 655350 系统级最大文件句柄数
net.core.somaxconn 4096 65535 TCP 半连接队列上限,高并发 web 调大
net.ipv4.tcp_tw_reuse 0 1 允许 TIME_WAIT 套接字复用,短连接多的服务有用

注意区分两个句柄限制:fs.file-max 是全系统上限,ulimit -n 是单进程上限。调了前者不调后者,业务进程照样报 too many open files。

五、⚠️ 常见错误

  1. modprobe: module xxx not found :多半是内核版本对不上。装的是另一个内核的头文件/模块包,uname -r 看当前跑的内核,模块得装到那个版本的目录里。
  2. 卸载模块报 in use :lsmod 最后一列看谁在用,把使用者停掉再卸。网卡先 ip link set eth0 down,存储先卸载文件系统。
  3. 改 sysctl 重启失效 :sysctl -w 是临时的。永久配置必须写 /etc/sysctl.d/*.conf 或 /etc/sysctl.conf,再 sysctl -p。
  4. 升级内核后起不来旧模块 :第三方编译的内核模块(比如某些显卡、虚拟化驱动)要针对新内核重新编译,dkms 包能自动做这件事。
  5. 改 /etc/sysctl.conf 不生效 :某些发行版读 /etc/sysctl.d/ 优先,或需要 sysctl --system 重新加载全部。

六、知识扩展:modules.dep 与 depmod

modprobe 怎么知道一个模块依赖谁?答案是 /lib/modules/$(uname -r)/modules.dep 这个文件。它里面记着每个 .ko 模块的完整依赖树。

手动往 /lib/modules/ 扔了一个新编译的 .ko,modprobe 一开始不认识它,得跑:

bash 复制代码
sudo depmod -a

depmod 扫描一遍所有 .ko,重新生成 modules.dep。之后 modprobe 才能找到。

系统升级内核、装 dkms 包时,这些步骤都是脚本自动跑的。自己手撸模块的时候忘了 depmod -a,就会出现"文件明明在,modprobe 却说找不到"的怪事。

模块加载失败时,dmesg 比 modprobe 的报错信息详细得多:

bash 复制代码
dmesg | tail -20

驱动版本不匹配、符号未找到、设备资源冲突,全在内核环形缓冲区里。modprobe 只告诉你"失败了",dmesg 告诉你"为什么"。

相关推荐
adinnet20265 小时前
多轮对话与上下文压缩:追问时模型怎么记住前面说的
数据库·microsoft
wdfk_prog5 小时前
Wi-Fi Direct教程 02:从 wpa_cli main() 到 P2P_FIND——用源码注释追踪 CLI 控制命令发送
运维·服务器·网络·网络协议·ubuntu·p2p·wifi-direct
skywalk81635 小时前
Deepseek harness的4种模式 配置文件内容
linux·人工智能·ubuntu·deepseek·harness
JosieBook5 小时前
【数据库】MySQL 实战精通系列 · 第11篇:Redis 缓存与 MySQL 一致性实战
数据库·mysql·缓存
HRTOS6 小时前
HRTOS Shell继续完善:优化printf缓冲区与字符串越界保护,国庆后随新版本更新
运维·单片机·嵌入式硬件·算法·51单片机
智能RPA6 小时前
农业与矿业行业智能体自动化平台对比评测(计量与巡检场景)
运维·人工智能·python·自动化·agent·rpa
沫璃染墨6 小时前
《从零入门Linux系统篇(五十一):线程篇·四——pthread线程库详解:从线程创建到终止与分离》
linux·运维·服务器·开发语言·c++·系统架构·线程
YYRAN_ZZU6 小时前
GMSL开发加解串配置介绍
linux·嵌入式硬件
墨家前任巨子6 小时前
定时关机脚本
运维
云计算练习生6 小时前
什么是上下文切换?进程切换时 CPU 到底在保存什么
linux·服务器·操作系统·进程切换