Ubuntu 系统下通过网络传输内核至 QEMU 虚拟机的安装指南

本文以 **Ubuntu ** 为环境,详细介绍通过网络传输主机编译内核并在虚拟机中安装的完整流程,无需挂载虚拟机根文件系统,操作灵活且符合 Ubuntu 使用习惯。

1. 前提条件

  1. 内核文件准备:主机已完成内核编译(以 linux-6.1.0 为例),核心产物需存在:
    内核镜像:arch/x86/boot/bzImage

  2. 内核模块:编译目录下已完成 make modules 编译

  3. 符号表(可选,调试用):System.map

  4. 网络基础:QEMU 虚拟机已配置网络(能访问主机),且虚拟机内具备 wget/scp/sudo 权限。

  5. 环境匹配:主机与虚拟机架构一致(本文以 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. 总结

本方法核心流程可概括为“网络配置→主机准备→虚拟机下载→安装配置→验证生效”,无需挂载虚拟机根文件系统,适合虚拟机已部署、需远程更新内核的场景。关键注意事项:

  1. 虚拟机网络需确保与主机连通(核心 IP:10.0.2.2);

  2. 内核模块必须完整安装,否则会导致设备功能缺失;

  3. GRUB 配置更新是新内核生效的必要步骤。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeeplyMind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值