4. 虚拟化平台基础配置:启动脚本编写、内存与CPU分配、虚拟网络配置
好,咱们接着往下走。上一章我们把QHV(QNX Hypervisor)的架构和基本概念捋了一遍。这一章,咱们要动真格的了——动手配置一个能跑起来的虚拟化平台。
说白了,就是三件事:启动脚本怎么写、内存和CPU怎么分、虚拟网络怎么搭。这三件事搞定了,你的虚拟机就能“活”过来。
4.1 启动脚本编写:让虚拟机“自启动”
我个人习惯,先把启动脚本的骨架搭好。QNX的虚拟化启动,核心文件就是 .build 文件。这个文件告诉系统:你要启动哪些虚拟机,它们各自用什么资源。
来看一个最简的示例:
# 这是 host 的 build 文件片段
# 定义第一个虚拟机:Linux Guest
vm-guest1 {
# 虚拟机类型
type = linux;
# 启动镜像路径
image = /path/to/guest1/vmlinux;
# 内核参数
cmdline = "console=ttyS0 root=/dev/vda rw";
# 分配的内存大小(MB)
memory = 512;
# 分配的CPU核心(从0开始)
cpus = 0-1;
# 虚拟网卡
vnet {
# 网卡类型:virtio
type = virtio;
# 桥接到 host 的哪个网络接口
bridge = "br0";
# MAC 地址
mac = "00:16:3e:00:00:01";
}
}
嗯,这里要注意:type 字段决定了虚拟机启动时加载的引导方式。Linux 和 QNX 的引导流程不一样,别搞混了。我在项目中遇到过有人把 QNX 的虚拟机配成了 type = linux,结果启动到一半就卡死了。
type = generic,然后手动指定引导参数。不过我个人建议,能用原生类型就用原生类型,省心。
4.2 内存与CPU分配:别让虚拟机“饿着”
内存和CPU的分配,是虚拟化配置里最容易出问题的地方。你想想看,如果给一个实时性要求很高的QNX虚拟机只分了一个CPU核心,它跑着跑着就被Linux虚拟机抢了时间片,那后果...嗯,你懂的。
我一般遵循这个原则:
- 实时虚拟机(如QNX):分配独占的CPU核心,不要跟其他虚拟机共享。内存尽量给够,但别超过物理内存的70%。
- 非实时虚拟机(如Linux):可以共享CPU核心,但要做好cgroup限制。内存可以按需分配,但别让host swap。
来看一个更完整的配置示例:
# host 的 build 文件
vm-guest1 {
type = qnx;
image = /path/to/guest1/ifs;
cmdline = "root=/dev/hd0";
memory = 1024; # 1GB 内存
cpus = 0; # 独占 CPU 0
# 内存大页支持(提升性能)
hugepages = 2M;
}
vm-guest2 {
type = linux;
image = /path/to/guest2/vmlinux;
cmdline = "console=ttyS0 root=/dev/vda rw";
memory = 2048; # 2GB 内存
cpus = 1-3; # 共享 CPU 1-3
# CPU 亲和性设置
cpumask = 0xE; # 二进制 1110,对应 CPU 1,2,3
}
关于内存分配,我还有一个经验:别把内存分得太碎。比如你有 8GB 内存,与其分成 4 个 2GB 的虚拟机,不如分成 2 个 3GB 的虚拟机,剩下的 2GB 留给 host。碎片化的内存分配会导致 TLB 缺失率上升,性能下降明显。
4.3 虚拟网络配置:让虚拟机“联网”
虚拟网络这块,说白了就是让虚拟机之间、虚拟机与外部网络能通信。QNX 的虚拟化方案支持多种网络模型,我重点讲两种最常用的:
4.3.1 桥接模式(Bridge)
这种模式下,虚拟机就像一台独立的物理机,直接接入 host 的网络。配置起来也简单:
# host 端配置
# 创建桥接接口
io-pkt-v6-hc -d e1000 -p tcpip -o iface=br0,mac=00:16:3e:00:00:ff
# 将物理网卡加入桥接
ifconfig en0 down
brconfig br0 add en0
ifconfig en0 up
ifconfig br0 up
# 虚拟机配置(在 build 文件中)
vm-guest1 {
vnet {
type = virtio;
bridge = "br0";
mac = "00:16:3e:00:00:01";
}
}
这种模式的好处是配置简单,虚拟机可以直接获取 DHCP 地址。但缺点也很明显——所有流量都经过 host 的协议栈,性能有损耗。
4.3.2 直通模式(Passthrough)
如果你对网络性能要求极高(比如跑工业以太网协议),可以考虑直通模式。直接把物理网卡分配给某个虚拟机:
# 在 build 文件中
vm-guest1 {
# 直通物理网卡
passthrough {
device = "pci:0:0:1.0"; # PCI 地址
}
}
4.4 实战:一个完整的启动脚本示例
好了,理论讲完了,咱们来写一个完整的启动脚本。这个脚本会启动两个虚拟机:一个 QNX 做实时控制,一个 Linux 做人机界面。
# host.build
# 定义 host 网络
io-pkt-v6-hc -d e1000 -p tcpip -o iface=br0,mac=00:16:3e:00:00:ff
# 第一个虚拟机:QNX 实时控制
vm-qnx-rt {
type = qnx;
image = /images/qnx-rt.ifs;
cmdline = "root=/dev/hd0";
memory = 512;
cpus = 0; # 独占 CPU 0
vnet {
type = virtio;
bridge = "br0";
mac = "00:16:3e:00:00:01";
}
}
# 第二个虚拟机:Linux HMI
vm-linux-hmi {
type = linux;
image = /images/linux-hmi/vmlinux;
cmdline = "console=ttyS0 root=/dev/vda rw";
memory = 2048;
cpus = 1-2; # 共享 CPU 1-2
vnet {
type = virtio;
bridge = "br0";
mac = "00:16:3e:00:00:02";
}
}
# 启动所有虚拟机
vm-start -all
这个脚本看起来简单,但我在实际项目中踩过不少坑。比如:
- 镜像路径写错:检查三遍!我曾经因为一个拼写错误,浪费了半天时间。
- MAC 地址冲突:每个虚拟机的 MAC 地址必须唯一,否则网络会乱套。
- CPU 核心重叠:如果两个虚拟机都分配了同一个 CPU 核心,性能会互相干扰。
vm-status 命令检查一下虚拟机的状态。如果某个虚拟机没起来,用 vm-log 查看日志。我曾经靠这个命令救回过一个项目——日志里明确写着“内存不足”,我一看,原来是给 Linux 虚拟机分了 4GB,但物理机总共才 4GB。
嗯,这一章的内容就到这里。启动脚本、内存CPU分配、虚拟网络配置,这三块是虚拟化平台的基础。下一章咱们会深入讲虚拟机的启动流程和调试技巧。到时候见!