Debian 系统初始化教程详解
作为系统管理员,粗略地了解 Debian 系统的启动和配置方式是明智的。尽管准确的细节在安装的软件包及对应的文档中,但这些知识对我们大多数人来说都是必须掌握的。
下面是 Debian 系统初始化的要点概述。由于 Debian 系统在不断发展,您应该参考最新的文档。
Debian Linux 内核手册 是关于 Debian 内核的主要信息来源。
bootup
(7) 介绍了基于systemd
的系统启动流程。(近期的 Debian)boot
(7) 介绍了基于 UNIX System V Release 4 的系统启动流程。(旧版的 Debian)
3.1. 启动过程概述
计算机系统从上电事件到能为用户提供完整的操作系统(OS)功能为止,需要经历几个阶段的启动过程。
为简便起见,笔者将讨论范围限定在具有默认安装的典型 PC 平台上。
典型的启动过程像是一个四级的火箭。每一级火箭将系统控制权交给下一级。
第 3.1.1 节 “第一阶段:UEFI”
第 3.1.2 节 “第二阶段:引载加载程序”
第 3.1.3 节 “第三阶段:迷你 Debian 系统”
第 3.1.4 节 “第四阶段:常规 Debian 系统”
当然,这些阶段可以有不同的配置。比如,你编译了自己的内核,则可能会跳过迷你 Debian 系统的步骤。因此,在读者亲自确认之前,请勿假定自己系统的情况也是如此。
3.1.1. 第一阶段:UEFI
Unified Extensible Firmware Interface (UEFI) 统一可扩展固件接口 定义了启动管理器作为 UEFI 规范的一部分。当一个计算机打开电源,启动管理器是启动流程的第一阶段,它检查启动配置并基于启动配置的设置,执行特定的操作系统引导加载程序或操作系统内核(通常是引导加载程序)。启动配置通过变量存储在 NVRAM,变量包括指示操作系统引导加载程序或操作系统内核的文件系统路径的变量。
EFI system partition (ESP) EFI 系统分区 是一个数据存储设备分区,在计算机里用来遵照 UEFI 规范。当计算机打开电源时,由 UEFI 固件来访问,它存储了 UEFI 应用程序和这些应用程序运行所需要的文件,包括操作系统的引导加载程序。(在老的 PC 系统,存放在 MBR 里的 BIOS 可以用来代替。)
3.1.2. 第二阶段:引载加载程序
引导加载程序是启动过程的第二阶段,由 UEFI 启动。引导加载程序将系统内核映像和 initrd 映像加载到内存并将控制权交给它们。initrd 映像是根文件系统映像,其支持程度依赖于所使用的引导加载程序。
Debian 系统通常使用 Linux 内核作为默认的系统内核。当前的 5.x Linux 内核的 initrd 映像在技术上是 initramfs(初始 RAM 文件系统)映像。
有许多引导加载程序和配置选项存在。
表 3.1. 引导加载程序列表
软件包 | 流行度 | 大小 | initrd | 引导加载程序 | 说明 |
---|---|---|---|---|---|
grub-efi-amd64 | I:339 | 184 | 支持 | GRUB UEFI | 可智能识别磁盘分区和文件系统,例如 vfat、ext4…(UEFI) |
grub-pc | V:21, I:634 | 557 | 支持 | GRUB 第 2 版 | 可智能识别磁盘分区和文件系统,例如 vfat、ext4…(BIOS) |
grub-rescue-pc | V:0, I:0 | 6625 | 支持 | GRUB 第 2 版 | 此为 GRUB 第 2 版的可引导修复映像(CD 和软盘)(PC / BIOS 版本) |
syslinux | V:3, I:36 | 344 | 支持 | Isolinux | 可识别 ISO9660 文件系统。引导 CD 使用此项。 |
syslinux | V:3, I:36 | 344 | 支持 | Syslinux | 可识别 MSDOS 文件系统(FAT)。引导软盘使用此项。 |
loadlin | V:0, I:0 | 90 | 支持 | Loadlin | 新系统从 FreeDOS 或 MSDOS 中启动。 |
mbr | V:0, I:4 | 47 | 不支持 | Neil Turton 的 MBR | 此为取代 MSDOS MBR 的自由软件。只可识别硬盘分区。 |
对于 UEFI 系统,GRUB2 首先读取 ESP 分区,使用 "/boot/efi/EFI/debian/grub.cfg
"里面 search.fs_uuid
指定的 UUID 来确定 GRUB2 菜单配置文件 "/boot/grub/grub.cfg
" 所在的分区。
GRUB2 菜单配置文件的关键部分看起来像:
menuentry 'Debian GNU/Linux' ... { load_video insmod gzio insmod part_gpt insmod ext2 search --no-floppy --fs-uuid --set=root fe3e1db5-6454-46d6-a14c-071208ebe4b1 echo 'Loading Linux 5.10.0-6-amd64 ...' linux /boot/vmlinuz-5.10.0-6-amd64 root=UUID=fe3e1db5-6454-46d6-a14c-071208ebe4b1 ro quiet echo 'Loading initial ramdisk ...' initrd /boot/initrd.img-5.10.0-6-amd64 }
对于这部分的 /boot/grub/grub.cfg
,这个菜单条目的意义如下。
表 3.2. /boot/grub/grub.cfg
文件上面部分菜单条目意义
设置 | 值 |
---|---|
GRUB2 模块加载 | gzio , part_gpt , ext2 |
使用的根文件系统分区 | 由 UUID=fe3e1db5-6454-46d6-a14c-071208ebe4b1 指定的分区标识 |
内核镜像文件在根文件系统中的路径 | /boot/vmlinuz-5.10.0-6-amd64 |
使用的内核启动参数 | "root=UUID=fe3e1db5-6454-46d6-a14c-071208ebe4b1 ro quiet " |
initrd 镜像文件在根文件系统中的路径 | /boot/initrd.img-5.10.0-6-amd64 |
![]() | 提示 |
---|---|
通过删除 " |
参见 “info grub
” 及 grub-install
(8)。
3.1.3. 第三阶段:迷你 Debian 系统
迷你 Debian 系统是启动流程的第三阶段,由引导加载程序启动。它会在内存中运行系统内核和根文件系统。这是启动流程的一个可选准备阶段。
![]() | 注意 |
---|---|
“迷你 Debian 系统”是笔者自创的术语,用于在本文档中描述启动流程的第三个阶段。这个系统通常被称为 initrd 或 initramfs 系统。内存中类似的系统在 Debian 安装程序中使用。 |
/init
程序是内存中的根文件系统上执行的第一个程序。这个程序在用户空间把内核初始化,并把控制权交给下一阶段。迷你 Debian 系统能够在主引导流程之前添加内核模块或以加密形式挂载根文件系统,使引导流程更加灵活。
如果 initramfs 是由
initramfs-tools
创建,则"/init
" 程序是一个 shell 脚本程序。通过给内核添加 “
break=init
" 等启动参数,你可以中断这部分启动流程以获取 root shell。更多中断条件请参见 ”/init
“ 脚本。这个 shell 环境已足够成熟,你可通过它很好地检查机器的硬件。迷你 Debian 系统中可用的命令是精简过的,且主要由一个称为
busybox
(1) 的 GNU 工具提供。如果 initramfs 是由
dracut
创建,则 "/init
" 程序是一个二进制systemd
程序。迷你 Debian 系统中可用的命令是一个精简过的
systemd
(1) 环境。
3.1.4. 第四阶段:常规 Debian 系统
常规 Debian 系统是启动流程的第四阶段,由迷你 Debian 系统启动。迷你 Debian 系统的内核在此环境下继续运行。根文件系统将由内存切换到实际的硬盘文件系统上。
init 程序是系统执行的第一个程序(PID=1),它启动其它各种程序以完成主引导流程。init 程序的默认路径是 ”/usr/sbin/init
“,但可通过内核启动参数修改,例如 ”init=/path/to/init_program
"。
在 Debian 8 jessie(2015 年发布)版本后,"/usr/sbin/init
" 是一个到 "/lib/systemd/systemd
" 的符号链接。
表 3.3. Debian 系统启动工具列表
软件包 | 流行度 | 大小 | 说明 |
---|---|---|---|
systemd | V:860, I:966 | 11168 | 基于事件且支持并发的 init (8) 守护进程(可替代 sysvinit ) |
cloud-init | V:3, I:5 | 2870 | 云实例架构的初始化系统 |
systemd-sysv | V:832, I:964 | 80 | systemd 需用的用以代替 sysvinit 的手册页和符号链接 |
init-system-helpers | V:699, I:974 | 130 | 在 sysvinit 和 systemd 之间进行转换的帮助工具 |
initscripts | V:33, I:133 | 198 | 用于初始化和关闭系统的脚本 |
sysvinit-core | V:4, I:5 | 361 | 类 System V 的 init (8) 工具 |
sysv-rc | V:66, I:145 | 88 | 类 System V 的运行级别修改机制 |
sysvinit-utils | V:897, I:999 | 102 | 类 System V 的实用工具(startpar (8),bootlogd (8),……) |
lsb-base | V:634, I:675 | 12 | Linux 标准规范 3.2 版的 init 脚本功能 |
insserv | V:88, I:144 | 132 | 利用 LSB init.d 脚本依赖性来组织启动步骤的工具 |
kexec-tools | V:1, I:6 | 316 | 用于 kexec (8) 重启(热启动)的 kexec 工具 |
systemd-bootchart | V:0, I:0 | 131 | 启动流程性能分析器 |
mingetty | V:0, I:2 | 36 | 仅包含控制台的 getty (8) |
mgetty | V:0, I:0 | 315 | 可智能调制解调的 getty (8) 替代品 |
3.2. Systemd
3.2.1. Systemd 初始化
当 Debian 系统启动,/usr/sbin/init
符号链接到的 /usr/lib/systemd
作为初始系统进程 (PID=1
) 启动,该进程由 root (UID=0
)所有。参见 systemd
(1)。
The systemd
init process spawns processes in parallel based on the unit configuration files (see systemd.unit
(5)) which are written in declarative style instead of SysV-like procedural style.
派生的进程被放在一个单独的 Linux control groups,在单元后命名,它们属于一个私有的 systemd 层级结构(参见 cgroups 和 第 4.7.5 节 “Linux 安全特性”)。
系统模式单元从 systemd.unit
(5)描述中的"System Unit Search Path" 加载。主要部分是按照下列优先权顺序:
"
/etc/systemd/system/*
": 管理员创建的系统单元文件"
/run/systemd/system/*
": 运行时单元文件"
/lib/systemd/system/*
": 发行版软件包管理器安装的系统单元文件
他们的相互依赖关系通过"Wants=
", "Requires=
", "Before=
", "After=
", … 等指示来配置,(参见 systemd.unit
(5) 里的 "MAPPING OF UNIT PROPERTIES TO THEIR INVERSES")。 资源控制也是被定义 (参见 systemd.resource-control
(5)).
根据单元配置文件的后缀来区分它们的类型:
*.service 描述由
systemd
控制和监管的进程.参见systemd.service
(5).*.device 描述在
sysfs
(5) 里面作为udev
(7) 设备树展示的设备。参见systemd.device
(5).*.mount 描述由
systemd
控制和监管的文件系统挂载点。参见systemd.mount
(5).*.automount 描述由
systemd
控制和监管的文件系统自动挂载点。参见systemd.automount
(5).*.swap 描述由
systemd
控制和监管的 swap 文件或设备。参见systemd.swap
(5).*.path 描述被
systemd
监控的路径,用于基于路径的活动。参见systemd.path
(5).*.socket 描述被
systemd
控制和监管的套接字,用于基于套接字的活动。参见systemd.socket
(5).*.timer 描述被
systemd
控制和监管的计时器,用于基于时间的活动。参见systemd.timer
(5).*.slice 管理
cgroups
(7) 的资源。参见systemd.slice
(5).*.scope 使用
systemd
的总线接口来程序化的创建,用以管理一系列系统进程。 参见systemd.scope
(5).*.target 把其它单元配置文件分组,在启动的时候,来创建同步点。参见
systemd.target
(5).
系统启动时(即,init),systemd
进程会尝试启动"/lib/systemd/system/default.target
(通常是到"graphical.target
"的符号链接)。首先,一些特殊的 target 单元(参见 systemd.special
(7)),比如 "local-fs.target
"、"swap.target
"和"cryptsetup.target
"会被引入以挂载文件系统。之后,其它 target 单元也会根据单元依赖关系而被引入。详细情况,请阅读 bootup
(7)。
systemd
提供向后兼容的功能。在 "/etc/init.d/rc[0123456S].d/[KS]name
" 里面的 SysV 风格的启动脚本仍然会被分析;telinit
(8) 会被转换为 systemd 的单元活动请求。
3.2.2. Systemd 登录
当一个用户通过 gdm3
(8)、sshd
(8)等登录到 Debian 系统,/lib/systemd/system --user
作为用户服务管理器进程启动,并由相应的用户所有。参见 systemd
(1)。
systemd
初始化进程基于单元配置文件 (参见 systemd.unit
(5)) 来并行派生进程,这些单元配置文件使用声明样式来书写,代替之前的类 SysV 的过程样式。这些单元配置文件从下面的一系列路径来加载 (参见 systemd-system.conf
(5)) 。
用户模式单元从 systemd.unit
(5)描述中的"User Unit Search Path" 加载。主要部分是按照下列优先权顺序:
"
~/.config/systemd/user/*
": 用户配置单元文件"
/etc/systemd/user/*
": 管理员创建的用户单元文件"
/run/systemd/user/*
": 用户运行时单元文件"
/lib/systemd/user/*
": 发行版软件包管理器安装的用户单元文件
这些是和 第 3.2.1 节 “Systemd 初始化” 用同样的方式管理。
3.3. 内核消息
在控制台上显示的内核错误信息,能够通过设置他们的阈值水平来配置。
# dmesg -n3
表 3.4. 内核错误级别表
错误级别值 | 错误级别名称 | 说明 |
---|---|---|
0 | KERN_EMERG | 系统不可用 |
1 | KERN_ALERT | 行为必须被立即采取 |
2 | KERN_CRIT | 危险条件 |
3 | KERN_ERR | 错误条件 |
4 | KERN_WARNING | 警告条件 |
5 | KERN_NOTICE | 普通但重要的条件 |
6 | KERN_INFO | 信息提示 |
7 | KERN_DEBUG | debug 级别的信息 |
3.4. 系统消息
在 systemd
下, 内核和系统的信息都通过日志服务 systemd-journald.service
(又名 journald
)来记录,放在"/var/log/journal
"下的不变的二进制数据,或放在"/run/log/journal/
"下的变化的二进制数据.这些二进制日志数据,可以通过 journalctl
(1) 命令来访问。例如,你可以显示从最后一次启动以来的日志,按如下所示:
$ journalctl -b
表 3.5. 典型的 journalctl
命令片段列表
操作 | 命令片段 |
---|---|
查看从最后一次启动开始的系统服务和内核日志 | "journalctl -b --system " |
查看从最后一次启动开始的当前用户的服务日志 | "journalctl -b --user " |
查看从最后一次启动开始的 "$unit " 工作日志 | "journalctl -b -u $unit " |
查看从最后一次启动开始的 "$unit "的工作日志 ("tail -f " 式样) | "journalctl -b -u $unit -f " |
在 systemd
下,系统日志工具 rsyslogd
(8) 可以被卸载。如果安装了它,它会改变它的行为来读取易失性二进制日志数据(代替在 systemd 之前默认的 "/dev/log
")并创建传统的永久性 ASCII 系统日志数据。"/etc/default/rsyslog
" 和 "/etc/rsyslog.conf
" 能够自定义日志文件和屏幕显示。参见 rsyslogd
(8) 和 rsyslog.conf
(5),也可以参见第 9.3.2 节 “日志分析”。
3.5. 系统管理
systemd
不仅仅提供系统初始化,还用 systemctl
(1) 命令提供通用的系统管理操作。
表 3.6. 典型的 systemctl
命令片段列表
操作 | 命令片段 |
---|---|
列出所有存在的单元类型 | "systemctl list-units --type=help " |
列出内存中所有 target 单元 | "systemctl list-units --type=target " |
列出内存中所有 service 单元 | "systemctl list-units --type=service " |
列出内存中所有 device 单元 | "systemctl list-units --type=device " |
列出内存中所有 mount 单元 | "systemctl list-units --type=mount " |
列出内存中所有 socket 单元 | "systemctl list-sockets " |
列出内存中所有 timer 单元 | "systemctl list-timers " |
启动 "$unit " | "systemctl start $unit " |
停止 "$unit " | "systemctl stop $unit " |
重新加载服务相关的配置 | "systemctl reload $unit " |
停止和启动所有 "$unit " | "systemctl restart $unit " |
启动 "$unit " 并停止所有其它的 | "systemctl isolate $unit " |
转换到 "图形 " (图形界面系统) | "systemctl isolate graphical " |
转换到 "多用户 " (命令行系统) | "systemctl isolate multi-user " |
转换到 "应急模式 " (单用户命令行系统) | "systemctl isolate rescue " |
向"$unit "发送杀死信号 | "systemctl kill $unit " |
检查"$unit "服务是否是活动的 | "systemctl is-active $unit " |
检查"$unit "服务是否是失败的 | "systemctl is-failed $unit " |
检查"$unit|$PID|device "的状态 | "systemctl status $unit|$PID|$device " |
显示"$unit|$job "的属性 | "systemctl show $unit|$job " |
重设失败的"$unit " | "systemctl reset-failed $unit" |
列出所有单元服务的依赖性 | "systemctl list-dependencies --all " |
列出安装在系统上的单元文件 | "systemctl list-unit-files " |
启用 "$unit " (增加符号链接) | "systemctl enable $unit " |
禁用 "$unit " (删除符号链接) | "systemctl disable $unit " |
取消遮掩 "$unit " (删除到 "/dev/null " 的符号链接) | "systemctl unmask $unit " |
遮掩 "$unit " (增加到 "/dev/null " 的符号链接) | "systemctl mask $unit " |
获取默认的 target 设置 | "systemctl get-default " |
设置默认 target 为"graphical " (图形系统) | "systemctl set-default graphical " |
设置默认的 target 为"multi-user " (命令行系统) | "systemctl set-default multi-user " |
显示工作环境变量 | "systemctl show-environment " |
设置环境变量 "variable " 的值为 "value " | "systemctl set-environment variable=value " |
取消环境变量 "variable " 的设置 | "systemctl unset-environment variable " |
重新加载所有单元文件和后台守护进程(daemon) | "systemctl daemon-reload " |
关闭系统 | "systemctl poweroff " |
关闭和重启系统 | "systemctl reboot " |
挂起系统 | "systemctl suspend " |
休眠系统 | "systemctl hibernate " |
这里, 上面例子中的"$unit
",可以是一个单元名(后缀.service
和 .target
是可选的),或者,在很多情况下,也可以是匹配的多个单元 (shell 式样的全局通配符"*
", "?
", "[]
",通过使用 fnmatch
(3) ,来匹配目前在内存中的所有单元的基本名称).
上面列子的系统状态改变命令,通常是通过"sudo
"来处理,用以获得需要的系统管理权限。
"systemctl status $unit|$PID|$device
" 的输出使用有颜色的点("●")来概述单元状态,让人看一眼就知道。
白色的 "●" 表示一个 "不活动"或"变为不活动中"的状态。
红色的 "●"表示“失败”或者“错误”状态。
绿色"●"表示“活动”、“重新加载中”或“激活中”状态。
3.6. 其它系统监控
这里是 systemd
下其它零星的监控命令列表。请阅读包括 cgroups
(7) 在内的相关的 man 手册页。
表 3.7. systemd
下其它零星监控命令列表
操作 | 命令片段 |
---|---|
显示每一个初始化步骤所消耗的时间 | "systemd-analyze time " |
列出所有单元的初始化时间 | "systemd-analyze blame " |
加载"$unit "文件并检测错误 | "systemd-analyze verify $unit " |
简洁的显示用户调用会话的运行时状态信息 | "loginctl user-status " |
简洁的显示调用会话的运行时状态信息 | "loginctl session-status " |
跟踪 cgroups 的启动过程 | "systemd-cgls " |
跟踪 cgroups 的启动过程 | "ps xawf -eo pid,user,cgroup,args " |
跟踪 cgroups 的启动过程 | 读取 "/sys/fs/cgroup/ " 下的 sysfs |
3.7. 系统配置
3.7.1. 主机名
内核维护系统主机名。在启动的时候,通过 systemd-hostnamed.service
启动的系统单位设置系统的主机名,此主机名保存在 "/etc/hostname
"。这个文件应该只包含系统主机名,而不是全称域名。
不带参数运行 hostname
(1) 命令可以打印出当前的主机名。
3.7.2. 文件系统
硬盘和网络文件系统的挂载选项可以在 "/etc/fstab
" 中设置,参见 fstab
(5) 和 第 9.6.7 节 “通过挂载选项优化文件系统”。
加密文件系统的配置设置在“/etc/crypttab
”中。参见 crypttab
(5)
软 RAID 的配置 mdadm
(8) 设置在 "/etc/mdadm/mdadm.conf
". 参见 mdadm.conf
(5).
3.7.3. 网络接口初始化
对于使用 systemd
的现代 Debian 桌面系统,网络接口通常由两个服务进行初始化:lo
接口通常在“networking.service
”处理,而其它接口则由“NetworkManager.service
”处理。
参见 第 5 章 网络设置 来获取怎样来配置它们的信息。
3.7.4. 云系统初始化
云系统实例可以由 "Debian Official Cloud Images" 或类似的镜像启动。对于这样的系统实例,主机名、文件系统、网络、语言环境、SSH 密钥、用户和组等个性化信息,可以使用 cloud-init
和 netplan.io
软件包提供的功能来配置,利用多个数据源,放在原始系统镜像里面的文件和在启动过程中提供的外部数据。这些软件包使用 YAML 数据来声明系统配置。
更多信息参见 "Cloud Computing with Debian and its descendants", "Cloud-init documentation" 和 第 5.4 节 “现代云网络配置”。
3.7.5. 调整 sshd 服务的个性化例子
使用默认安装,通过 systemd
启动的过程中,在 network.target
启动后,很多网络服务 (参见 第 6 章 网络应用)作为后台守护进程(daemon)启动。 "sshd
" 也不列外。让我们修改为按需启动"sshd
" 作为一个定制化的例子。
首先,禁用系统安装的服务单元。
$ sudo systemctl stop sshd.service $ sudo systemctl mask sshd.service
传统 Unix 服务的按需套接字激活(on-demand socket activation)系统由 inetd
(或 xinetd
)超级服务来提供。在 systemd
下, 相同功能能够通过增加*.socket 和 *.service 单元配置文件来启用。
sshd.socket
用来定义一个监听的套接字
[Unit] Description=SSH Socket for Per-Connection Servers [Socket] ListenStream=22 Accept=yes [Install] WantedBy=sockets.target
sshd@.service
作为 sshd.socket
匹配的服务文件
[Unit] Description=SSH Per-Connection Server [Service] ExecStart=-/usr/sbin/sshd -i StandardInput=socket
然后重新加载。
$ sudo systemctl daemon-reload
3.8. udev 系统
从 Linux 内核 2.6 版开始,udev 系统 提供了自动硬件发现和初始化机制。(参见 udev
(7)).在内核发现每个设备的基础上,udev 系统使用从 sysfs 文件系统 (参见 第 1.2.12 节 “procfs 和 sysfs”)的信息启动一个用户进程,使用 modprobe
(8) 程序 (参见 第 3.9 节 “内核模块初始化”)加载支持它所要求的内核模块, 创建相应的设备节点。
由于 udev 系统是一个正在变化的事物,我在其它文档进行了详细描述,在这里只提供了最少的信息。
3.9. 内核模块初始化
通过 modprobe
(8) 程序添加和删除内核模块,使我们能够从用户进程来配置正在运行的 Linux 内核。udev 系统(参见 第 3.8 节 “udev 系统”)自动化它的调用来帮助内核模块初始化。
下面的非硬件模块和特殊的硬件驱动模块,需要被预先加载,把它们在"/etc/modules
"文件里列出 (参见 modules
(5)).
TUN/TAP 模块提供虚拟的 Point-to-Point 网络设备 (TUN) 和虚拟的 Ethernet 以太网网络设备 (TAP),
netfilter 模块提供 netfilter 防火墙能力(
iptables
(8), 第 5.7 节 “Netfilter 网络过滤框架”),watchdog timer 驱动模块。
modprobe
(8) 程序的配置文件是按 modprobe.conf
(5)的说明放在"/etc/modprobes.d/
" 目录下,(如果你想避免自动加载某些内核模块,考虑把它们作为黑名单放在"/etc/modprobes.d/blacklist
" 文件里.)
"/lib/modules/version/modules.dep
" 文件由 depmod
(8) 程序生成,它描述了 modprobe
(8) 程序使用的模块依赖性.
modinfo
(8) 程序显示 Linux 内核模块信息。
lsmod
(8) 程序以好看的格式展示"/proc/modules
"的内容,显示当前内核加载了哪些模块。