本文以 **Ubuntu ** 为环境,详细介绍通过网络传输主机编译内核并在虚拟机中安装的完整流程,无需挂载虚拟机根文件系统,操作灵活且符合 Ubuntu 使用习惯。
1. 前提条件
-
内核文件准备:主机已完成内核编译(以
linux-6.1.0为例),核心产物需存在:
内核镜像:arch/x86/boot/bzImage -
内核模块:编译目录下已完成
make modules编译 -
符号表(可选,调试用):
System.map -
网络基础:QEMU 虚拟机已配置网络(能访问主机),且虚拟机内具备
wget/scp/sudo权限。 -
环境匹配:主机与虚拟机架构一致(本文以 x86_64 为例,ARM 架构仅路径需调整)。
2. 配置 QEMU 虚拟机网络(确保连通性)
核心是通过 QEMU 网络参数实现虚拟机与主机的通信,推荐使用 user 网络(NAT 模式,无需额外配置),并配置端口转发方便文件传输。
2.1 启动带网络配置的虚拟机
主机终端执行以下命令,启动虚拟机并配置网络:
qemu-system-x86_64 \
-nographic \ # 无图形界面,仅命令行
-kernel ~/linux-6.1.0/arch/x86/boot/bzImage \ # 临时用旧内核启动
-drive file=ubuntu22.04-rootfs.ext4,format=raw,if=virtio \ # 虚拟机根文件系统
-append "console=ttyS0 root=/dev/vda rw" \ # 内核参数,指定控制台和根分区
-m 2048 \ # 分配 2G 内存
-smp 2 \ # 分配 2 核 CPU
-net nic -net user,hostfwd=tcp::2222-:22 # 核心:开启网络,主机2222端口→虚拟机22端口
参数说明:
-
-net nic -net user:启用 QEMU 用户网络,虚拟机默认网关为10.0.2.2(即主机的网络映射 IP)。 -
hostfwd=tcp::2222-:22:端口转发,后续可通过主机 2222 端口 SSH 连接虚拟机。
2.2 验证虚拟机网络连通性
虚拟机启动后,在其控制台执行以下命令,测试与主机的连通性:
# ping 主机映射 IP(10.0.2.2),发送3个数据包后停止
ping -c 3 10.0.2.2
若输出“3 packets transmitted, 3 received”,说明网络正常;若不通,检查 QEMU 启动参数是否包含网络配置,或临时关闭主机防火墙(sudo ufw disable)。
3. 主机端准备内核文件(打包+暴露服务)
主机需将内核镜像、模块等文件整理打包,并通过 HTTP 服务暴露,供虚拟机下载。
3.1 编译并打包内核模块
内核模块需完整传输,先编译(若未完成)再打包,避免传输零散文件:
# 1. 进入内核编译目录
cd ~/linux-6.1.0
# 2. 编译内核模块(-j 后跟CPU核心数,加速编译,如 -j8)
make modules -j$(nproc)
# 3. 创建临时目录,存放待传输的内核文件
mkdir -p ~/kernel-files
# 4. 复制内核镜像到临时目录,并命名为易识别格式
cp arch/x86/boot/bzImage ~/kernel-files/vmlinuz-6.1.0-custom
# 5. 复制内核符号表(可选,调试用)
cp System.map ~/kernel-files/System.map-6.1.0-custom
# 6. 安装模块到临时目录(模拟模块安装路径)
sudo make INSTALL_MOD_PATH=~/kernel-files modules_install
# 7. 打包模块目录(减小传输体积)
cd ~/kernel-files
tar -zcvf modules-6.1.0-custom.tar.gz lib/modules/6.1.0-custom/
执行完成后,~/kernel-files 目录下会生成 3 个核心文件:
-
vmlinuz-6.1.0-custom:重命名后的内核镜像 -
System.map-6.1.0-custom:内核符号表 -
modules-6.1.0-custom.tar.gz:打包后的内核模块
3.2 主机启动 HTTP 服务
使用 Python 内置 HTTP 服务器,暴露 kernel-files 目录,无需安装额外软件:
# 进入内核文件目录
cd ~/kernel-files
# 启动 HTTP 服务,端口 8000(默认端口,可修改)
python3 -m http.server 8000
注意:保持该终端打开,服务运行中虚拟机才能下载文件;关闭终端会终止服务。此时虚拟机可通过 http://10.0.2.2:8000 访问主机的内核文件。
4. 虚拟机内下载并安装内核文件
虚拟机通过 HTTP 服务下载内核文件后,依次完成镜像安装、模块部署。
4.1 下载内核文件到虚拟机
在虚拟机控制台执行以下命令,从主机下载文件:
# 1. 创建临时目录,存放下载的文件
mkdir -p ~/kernel-tmp
cd ~/kernel-tmp
# 2. 下载内核镜像(主机映射IP:10.0.2.2,端口:8000)
wget http://10.0.2.2:8000/vmlinuz-6.1.0-custom -O vmlinuz-6.1.0-custom
# 3. 下载模块压缩包
wget http://10.0.2.2:8000/modules-6.1.0-custom.tar.gz -O modules-6.1.0-custom.tar.gz
# 4. (可选)下载内核符号表
wget http://10.0.2.2:8000/System.map-6.1.0-custom -O System.map-6.1.0-custom
# 验证下载:查看文件是否存在
ls -lh
若输出包含上述 3 个文件,说明下载成功;若提示“Connection refused”,检查主机 HTTP 服务是否正常运行。
4.2 安装内核镜像到 /boot 目录
内核镜像需放置在虚拟机的 /boot 目录(GRUB 默认扫描该目录的内核文件),执行以下命令:
# 复制内核镜像和符号表到 /boot(需 sudo 权限)
sudo cp ~/kernel-tmp/vmlinuz-6.1.0-custom /boot/
sudo cp ~/kernel-tmp/System.map-6.1.0-custom /boot/
# 验证安装:查看 /boot 目录中的新内核文件
ls -lh /boot | grep 6.1.0-custom
4.3 安装内核模块(关键步骤)
内核模块提供驱动等核心功能,若不安装会导致网络、磁盘等设备无法正常工作:
# 1. 进入临时目录,解压模块包
cd ~/kernel-tmp
tar -zxvf modules-6.1.0-custom.tar.gz -C / # -C / 表示解压到根目录
# 2. 验证模块安装:查看模块目录
ls -lh /lib/modules/6.1.0-custom/
# 若看到 kernel/、modules.dep 等文件,说明安装成功
# 3. 更新模块依赖(让系统识别新模块)
sudo depmod -a 6.1.0-custom
5. 配置 GRUB 启动项(让系统识别新内核)
Ubuntu 虚拟机默认使用 GRUB 管理启动项,需更新 GRUB 配置,让系统检测到新内核。
5.1 更新 GRUB 配置
虚拟机控制台执行以下命令,GRUB 会自动扫描 /boot 目录的内核文件:
sudo update-grub
若输出“Found linux image: /boot/vmlinuz-6.1.0-custom”,说明新内核已被识别。
5.2 验证 GRUB 配置(可选)
查看 GRUB 配置文件,确认新内核启动项存在:
cat /boot/grub/grub.cfg | grep -A5 "6.1.0-custom"
正常输出示例:
menuentry 'Ubuntu, with Linux 6.1.0-custom' --class ubuntu --class gnu-linux {
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
linux /boot/vmlinuz-6.1.0-custom root=/dev/vda rw quiet splash
}
6. 重启虚拟机,验证新内核
完成上述配置后,重启虚拟机,确认新内核已正常加载。
6.1 关闭并重新启动虚拟机
# 1. 虚拟机内执行:关机
sudo poweroff
# 2. 主机执行:重新启动虚拟机(无需指定 -kernel 参数,GRUB 自动选择)
qemu-system-x86_64 \
-nographic \
-drive file=ubuntu22.04-rootfs.ext4,format=raw,if=virtio \
-append "console=ttyS0 root=/dev/vda rw" \
-m 2048 \
-smp 2 \
-net nic -net user,hostfwd=tcp::2222-:22
6.2 验证新内核生效
虚拟机启动后,在控制台执行以下命令验证:
# 1. 查看内核版本(应输出 6.1.0-custom)
uname -r
# 2. 查看内核详细信息(确认是主机编译的版本)
uname -a
# 3. 验证模块加载(如查看 virtio 网卡模块)
lsmod | grep virtio_net
# 4. 查看模块所属内核版本
modinfo virtio_net | grep "ver:"
若所有命令输出均与新内核匹配,说明内核已成功安装并生效。
7. 常见问题解决
问题 1:虚拟机 ping 不通主机(10.0.2.2)
-
检查 QEMU 启动参数是否包含
-net nic -net user; -
虚拟机内执行
ip a,确认网卡eth0已获取10.0.2.15段 IP; -
临时关闭主机防火墙:
sudo ufw disable(测试后可重新开启:sudo ufw enable)。
问题 2:update-grub 未识别新内核
-
检查内核镜像命名:需以
vmlinuz-开头(GRUB 默认扫描该前缀); -
检查
/boot目录权限:执行ls -ld /boot,确保权限为drwxr-xr-x; -
手动添加 GRUB 启动项(应急方案):
`# 编辑 GRUB 自定义配置文件
sudo vim /etc/grub.d/40_custom
添加以下内容(root=/dev/vda 需与虚拟机根分区匹配)
menuentry ‘Custom Kernel 6.1.0’ {
linux /boot/vmlinuz-6.1.0-custom root=/dev/vda rw console=ttyS0
initrd /boot/initrd.img-6.1.0-custom # 若有 initrd 镜像需添加
}
保存后更新 GRUB
sudo update-grub`
问题 3:内核启动后模块加载失败
-
确认模块安装路径:
/lib/modules/6.1.0-custom/必须存在且文件完整; -
重新执行模块依赖更新:
sudo depmod -a 6.1.0-custom; -
检查内核编译配置:确保
.config文件中CONFIG_MODULES=y(启用模块化)。
8. 总结
本方法核心流程可概括为“网络配置→主机准备→虚拟机下载→安装配置→验证生效”,无需挂载虚拟机根文件系统,适合虚拟机已部署、需远程更新内核的场景。关键注意事项:
-
虚拟机网络需确保与主机连通(核心 IP:
10.0.2.2); -
内核模块必须完整安装,否则会导致设备功能缺失;
-
GRUB 配置更新是新内核生效的必要步骤。
1万+

被折叠的 条评论
为什么被折叠?



