linux 内核模块
- 1. 内核相关命令与文件
- 内核模块存放位置
- 查看已加载内核模块
- 加载与卸载内核模块
- 修改内核参数
- 永久调整内核参数
- 2. 常用模块
- 进程调度模块
- 进程间通信模块
- 内存管理模块
- 文件系统模块
- 网络接口模块
Linux 内核采用的是模块化技术,这样的设计使得系统内核可以保持最小化,同时确保了内核的可扩展性与可维护性,模块化设计允许我们在需要时才将模块加载至内核,实现动态内核的调整。
1. 内核相关命令与文件
内核模块存放位置
Linux内核模块文件的命名方式通常为<模块名称.ko>
,CentOS 7 系统的内核模块被集中存放在/lib/modules/$(uname -r)/
目录下。
[root@node-139 ~]# ll /lib/modules/`uname -r`/
total 3304
lrwxrwxrwx. 1 root root 45 Dec 23 00:14 build -> /usr/src/kernels/3.10.0-1160.105.1.el7.x86_64
drwxr-xr-x. 2 root root 6 Dec 7 23:44 extra
drwxr-xr-x. 12 root root 128 Dec 23 00:14 kernel
-rw-r--r--. 1 root root 860346 Dec 23 00:19 modules.alias
-rw-r--r--. 1 root root 819751 Dec 23 00:19 modules.alias.bin
-rw-r--r--. 1 root root 1333 Dec 7 23:44 modules.block
-rw-r--r--. 1 root root 7426 Dec 7 23:44 modules.builtin
-rw-r--r--. 1 root root 9458 Dec 23 00:19 modules.builtin.bin
-rw-r--r--. 1 root root 270899 Dec 23 00:19 modules.dep
-rw-r--r--. 1 root root 379798 Dec 23 00:19 modules.dep.bin
-rw-r--r--. 1 root root 361 Dec 23 00:19 modules.devname
-rw-r--r--. 1 root root 140 Dec 7 23:44 modules.drm
-rw-r--r--. 1 root root 69 Dec 7 23:44 modules.modesetting
-rw-r--r--. 1 root root 1810 Dec 7 23:44 modules.networking
-rw-r--r--. 1 root root 97866 Dec 7 23:44 modules.order
-rw-r--r--. 1 root root 569 Dec 23 00:19 modules.softdep
-rw-r--r--. 1 root root 401068 Dec 23 00:19 modules.symbols
-rw-r--r--. 1 root root 492664 Dec 23 00:19 modules.symbols.bin
lrwxrwxrwx. 1 root root 5 Dec 23 00:14 source -> build
drwxr-xr-x. 2 root root 6 Dec 7 23:44 updates
drwxr-xr-x. 2 root root 95 Dec 23 00:14 vdso
drwxr-xr-x. 3 root root 23 Dec 23 00:19 weak-updates
查看已加载内核模块
lsmod
命令用来显示当前Linux
内核模块状态,不使用任何参数会显示当前已经加载的所有内核模块。输出的三列信息分别为模块名称
、占用内存大小
和是否在被使用
,如果第三列为0
,则该模块可以随时卸载,非0
则无法执行modprobe
删除模块
[root@node-139 ~]# lsmod
Module Size Used by
nls_utf8 12557 1
isofs 43940 1
loop 28072 2
rpcsec_gss_krb5 35549 0
tcp_diag 12591 0
udp_diag 12801 0
inet_diag 18949 2 tcp_diag,udp_diag
xt_CHECKSUM 12549 1
iptable_mangle 12695 1
...
[root@node-139 ~]# lsmod|awk '$3==0 {print $1,$3}'
rpcsec_gss_krb5 0
tcp_diag 0
udp_diag 0
bridge 0
ebtable_filter 0
ip6table_filter 0
devlink 0
snd_seq_midi 0
iosf_mbi 0
crc32_pclmul 0
...
加载与卸载内核模块
modprobe
命令可以动态加载与卸载内核模块
[root@node-137 ~]# modprobe ip_vs #加载
[root@node-137 ~]# lsmod|grep ip_vs
ip_vs 145458 0
nf_conntrack 143360 6 ip_vs,nf_nat,nf_nat_ipv4,xt_conntrack,nf_nat_masquerade_ipv4,nf_conntrack_ipv4
libcrc32c 12644 4 xfs,ip_vs,nf_nat,nf_conntrack
[root@node-137 ~]# modprobe -r ip_vs #卸载
[root@node-137 ~]# lsmod|grep ip_vs
[root@node-137 ~]#
modinfo
命令可以查看内核模块信息
[root@node-137 ~]# modinfo ip_vs
filename: /lib/modules/3.10.0-1160.92.1.el7.x86_64/kernel/net/netfilter/ipvs/ip_vs.ko.xz
license: GPL
retpoline: Y
rhelversion: 7.9
srcversion: 7C6456F1C909656E6093A8F
depends: nf_conntrack,libcrc32c
intree: Y
vermagic: 3.10.0-1160.92.1.el7.x86_64 SMP mod_unload modversions
signer: CentOS Linux kernel signing key
sig_key: 87:85:3C:C1:99:05:0D:FA:08:55:B0:16:21:67:A5:37:DF:72:CC:87
sig_hashalgo: sha256
parm: conn_tab_bits:Set connections' hash size (int)
通过上述modprobe
方式加载的内核模块仅在当前有效,计算机重启后并不会再次加载该模块,如果希望系统开机自动挂载内核模块,有几种方法,例如:
- 制作成系统服务:
创建一个新的系统服务,该服务在系统启动时调用modprobe
加载你的模块。这需要你创建一个新的systemd服务文件,如/etc/systemd/system/load-mydriver.service
,并添加以下内容:
[Unit]
Description=Load Mydriver module
[Service]
Type=oneshot ExecStart=/sbin/modprobe Mydriver [Install]
WantedBy=multi-user.target
然后使用systemctl命令启用并启动服务:
sudo systemctl enable load-mydriver.service sudo systemctl start load-mydriver.service
在下次启动时,系统就会自动加载“Mydriver”模块。
- 写入系统启动脚本,例如写入
/etc/rc.d/rc.local
这个方法对于 systemd-based 发行版 Linux 同样有效。不过,使用这个方法,需要授予/etc/rc.d/rc.local
文件执行权限:
echo "modprobe ip_vs">>/etc/rc.d/rc.local
chmod +x /etc/rc.d/rc.local
然后在这个文件底部添加命令
- 修改
/etc/modprobe.d/
目录中的相关配置文件实现
你可以在/etc/modprobe.d/目录下创建一个新的.conf文件,然后在文件中使用“install”命令来指定在加载某个模块时自动加载你的模块。例如,如果你想在加载usbcore模块时自动加载你的模块"Mydriver",可以创建一个文件/etc/modprobe.d/mydriver.conf,然后添加以下内容:
install usbcore /sbin/modprobe Mydriver; /sbin/modprobe --ignore-install usbcore
修改内核参数
- 临时调整内核参数
Linux内核参数随着系统的启动会被写入内存中,我们可以直接修改/proc
目录下的大量文件来调整内核参数,并且这种调整是立刻生效的,例如
开启内核路由转发功能(通过0或1设置开关)
[root@node-137 ~]# echo "1" > /proc/sys/net/ipv4/ip_forward
[root@node-137 ~]# sysctl -a |grep "ip_forward"
net.ipv4.ip_forward = 1
net.ipv4.ip_forward_use_pmtu = 0
...
禁止所有的icmp回包(禁ping本机)功能
[root@node-137 ~]# echo "1"> /proc/sys/net/ipv4/icmp_echo_ignore_all
[root@node-137 ~]# sysctl -a |grep "icmp"
net.ipv4.icmp_echo_ignore_all = 1
...
调整所有的进程可以打开的文件总数量
[root@node-137 ~]# echo "108248" > /proc/sys/fs/file-max
永久调整内核参数
通过man proc
可以获得大量关于内核参数的描述信息。但以上通过直接修改/proc
相关文件的方式在系统重启后将不再生效,如果希望设置参数永久生效,可以修改/etc/sysctl.conf
文件,文件格式为选项=值
,我们通过vim
修改该文件将前面三个实例参数设置为永久有效:
[root@node-139 ~]# cat /etc/sysctl.conf
...
net.ipv4.ip_forward=1
net.ipv4.icmp_echo_ignore_all=1
fs.file-max=100000
注意:通过sysctl.conf
文件修改的内核参数不会立即生效,修改完成后,使用sysctl -p
命令可以使这些设置立刻生效
[root@node-139 ~]# sysctl -p
net.ipv4.ip_forward = 1
net.ipv4.icmp_echo_ignore_all = 1
fs.file-max = 100000
2. 常用模块
Linux中的模块主要分为以下几种:进程调度模块、进程间通信模块、内存管理模块、文件系统模块以及网络接口模块
进程调度模块
Process Scheduler,也称作进程管理、进程调度。负责管理CPU资源,以便让各个进程可以以尽量公平的方式访问CPU。Linux以进程作为系统资源分配的基本单位,并采用动态优先级的进程高级算法,保证各个进程使用处理机的合理性。进程调度模块主要是对进程使用的处理机进行管理和控制。
进程调度是Linux内核中最重要的子系统,它主要提供对CPU的访问控制。因为在计算机中,CPU资源是有限的,而众多的应用程序都要使用CPU资源,所以需要“进程调度子系统”对CPU进行调度管理。
进程间通信模块
IPC(Inter-Process Communication),进程间通信。IPC不管理任何的硬件,它主要负责Linux系统中进程之间的通信。
进程间通信主要用于控制不同进程之间在用户空间的同步、数据共享和交换。由于不同的用户进程拥有不同的进程空间,因此进程间的通信要借助于内核的中转来实现。一般情况下,当一个进程等待硬件操作完成时,会被挂起。当硬件操作完成,进程被恢复执行,而协调这个过程的就是进程间的通信机制。
进程间通信模块保证了Linux支持多种进程间通信机制,包括管道、命名管道、消息队列、信号量和共享内存等。
内存管理模块
Memory Manager,内存管理。负责管理Memory(内存)资源,以便让各个进程可以安全地共享机器的内存资源。另外,内存管理会提供虚拟内存的机制,该机制可以让进程使用多于系统可用Memory的内存,不用的内存会通过文件系统保存在外部非易失存储器中,需要使用的时候,再取回到内存中。它提供了十分可靠的存储保护措施,对进程赋予不同的权限,用户不能直接访问系统的程序和数据,保证了系统的安全性。同时,为每个用户进程分配一个相互独立的虚拟地址空间。
文件系统模块
VFS(Virtual File System),虚拟文件系统。Linux内核将不同功能的外部设备,例如Disk设备(硬盘、磁盘、NAND Flash、Nor Flash等)、输入输出设备、显示设备等等,抽象为可以通过统一的文件操作接口(open、close、read、write等)来访问。这就是Linux系统“一切皆是文件”的体现。
Linux的文件系统模块采用先进的虚拟文件系统技术,屏蔽了各种文件系统的差别,为处理各种不同的文件系统提供了统一的接口,支持多种不同的物理文件系统达90多种。同时,Linux把各种硬件设备看作一种特殊的文件来处理,用管理文件的方法管理设备,非常方便、有效。
网络接口模块
Network,网络子系统,Linux具有最强大的网络功能。网络接口模块通过套接字机制实现计算机之间的网络通信,并采用网络层次模型提供对多种网络协议和网络硬件设备的支持。
网络接口提供了对各种网络标准的实现和各种网络硬件的支持。网络接口一般分为网络协议和网络驱动程序。网络协议部分负责实现每一种可能的网络传输协议。网络设备驱动程序则主要负责与硬件设备进行通信,每一种可能的网络硬件设备都有相应的设备驱动程序。