系统版本:X86
设备环境:虚拟机、
BUG现象:在pve底层架构下 fnos无法显示gpu利用率 显示为-1% 但是能够调用核显
出现频率:(必现)
title: 飞牛 fNOS 虚拟机直通 Intel 核显 — GPU 监控修复 + 硬件转码启用完整指南
date: 2026-05-14
tags: [fNOS, Proxmox, GPU直通, Intel核显, 硬件转码, 核显监控]
飞牛 fNOS 虚拟机直通 Intel 核显 — GPU 监控修复 + 硬件转码启用完整指南
背景
在 PVE(Proxmox VE)虚拟机中运行飞牛 fNOS,并且是把其他PVE的虚拟机里的FNOS迁移到另外一台PVE,通过 PCIe 直通将宿主机的 Intel 核显(如 UHD Graphics 630)分配给 fNOS 虚拟机,可以实现 GPU 硬件加速转码。但直通后你会发现两个问题:
- GPU 监控不显示 — fNOS 系统监控页面无法识别直通的核显
- GPU 转码无法启用 — mediasrv 服务找不到 GPU 设备
本文记录了完整的排查和修复过程,适用于 PVE + fNOS + Intel CoffeeLake 及更新的核显 环境。
环境说明
| 项目 |
配置 |
| 宿主机 |
Proxmox VE 8.x / 9.x |
| 虚拟机 |
fNOS(基于 Debian 12 bookworm) |
| 核显 |
Intel CoffeeLake-S UHD Graphics 630 (8086:3E91) |
| 内核 |
6.18.18-trim(fNOS 自定义内核) |
| i915 模块 |
i915-sriov-dkms(fNOS 自带的 SR-IOV 补丁版本) |
| mediasrv |
v0.8.35 |
| resmon_service |
fNOS 系统资源监控服务 |
适用范围:此方案基于 Intel UHD Graphics 630 测试,理论上也适用于 Intel Comet Lake(UHD 630)、Alder Lake(UHD 730/770)等核显。Alder Lake/Raptor Lake 等较新核显的 i915 配置参数可能不同。
第一步:PVE 宿主机 — 核显直通配置
1.1 开启 IOMMU
编辑 PVE 宿主机的 /etc/default/grub,在 GRUB_CMDLINE_LINUX_DEFAULT 中添加 intel_iommu=on iommu=pt:
# PVE 宿主机执行
nano /etc/default/grub
修改后的参数示例:
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"
更新 GRUB 并重启:
update-grub
reboot
1.2 确认 IOMMU 分组
重启后检查:
dmesg | grep -i iommu
# 应该看到 IOMMU enabled, DMAR 表等信息
lspci -nn | grep -i vga
# 找到核显的 PCI 地址,例如 00:02.0
1.3 fNOS 虚拟机添加 PCI 直通
在 PVE Web 界面中,对 fNOS 虚拟机执行以下操作:
- 硬件 → 添加 → PCI 设备:选择核显(通常显示为 Intel VGA)
- 勾选 所有功能(All Functions)和 ROM-Bar(如有选项)
- 勾选「主 GPU」(如果不需要虚拟显示输出,可以不勾选)
- 确认 VM 的 机器类型为
q35(推荐)
- 确认 VM 的 BIOS 为
OVMF (UEFI)
注意:如果你的 fNOS 虚拟机还需要 bochs 虚拟显卡作为控制台显示,不要将直通核显设为「主 GPU」。两者可以共存,核显仅用于转码。
第二步:fNOS 内 — 验证核显直通状态
进入 fNOS 虚拟机(SSH 或终端),确认核显已被识别:
# 查看 PCIe 设备
lspci | grep -i vga
你应该看到两个 VGA 设备:
00:02.0 VGA compatible controller: Device 1234:1111 (rev 02) ← bochs 虚拟显卡
00:10.0 VGA compatible controller: Intel Corporation CoffeeLake-S GT2 [UHD Graphics 630] ← 直通核显
检查核显驱动是否加载:
lspci -k -s 00:10.0
输出中应包含 Kernel driver in use: i915:
00:10.0 VGA compatible controller: Intel Corporation CoffeeLake-S GT2 [UHD Graphics 630]
Subsystem: Gigabyte Technology Co., Ltd CoffeeLake-S GT2 [UHD Graphics 630]
Kernel driver in use: i915
Kernel modules: i915
检查 DRI 设备是否创建:
ls -la /dev/dri/
正常情况应有:
card0 ← bochs 虚拟显卡
card1 ← Intel i915 核显
renderD128 ← VA-API 渲染节点
如果 /dev/dri/ 不存在或只有 card0,说明 i915 驱动未正常加载,请跳到「常见问题」部分的驱动排查章节。
第三步:修复 GPU 监控(核心问题)
3.1 问题根因
fNOS 的系统监控服务 resmon_service 通过加载共享库 /usr/trim/lib/libigputop.so 来读取 GPU 信息。这个 .so 文件中硬编码了核显的 PCI 路径为 0000:00:02.0:
- 物理机 / 非直通场景:核显默认在 PCI
00:02.0,直接匹配
- 虚拟机直通场景:核显被分配到其他 PCI 地址(如
00:10.0),路径不匹配导致监控失效
3.2 查看实际 PCI 地址
lspci | grep -i "Intel.*VGA\|Intel.*Graphics"
# 记下输出中的 PCI 地址前缀,例如 00:10.0
3.3 备份并修补 libigputop.so
⚠️ 修改系统文件有风险,请务必备份原文件。fNOS 系统更新可能会覆盖此修改,届时需要重新执行。
# 备份原文件
sudo cp /usr/trim/lib/libigputop.so /usr/trim/lib/libigputop.so.bak
# 查看原文件中的硬编码 PCI 路径(应看到 0000:00:02.0)
strings /usr/trim/lib/libigputop.so.bak | grep "0000:00"
# 将硬编码路径替换为你核显的实际 PCI 地址
# 格式: sed -i 's/原始地址/实际地址/g' 文件路径
sudo sed -i 's/0000:00:02.0/0000:00:10.0/g' /usr/trim/lib/libigputop.so
替换规则:0000:00:02.0 → 0000:00:XX.0,其中 XX 是你核显在 lspci 中显示的实际 PCI 总线号。
3.4 验证修补
# 查看替换结果(应显示你的实际 PCI 地址)
strings /usr/trim/lib/libigputop.so | grep "0000:00"
3.5 重启监控服务
sudo systemctl restart resmon_service
3.6 确认监控生效
# 检查服务日志,确认 GPU 被识别
journalctl -u resmon_service --no-pager -n 20
成功时会看到类似输出:
TRIMEVENT[xxxx]: GPU ** name, vid:8086, pid:3E91, sub dev id:00
此时进入 fNOS Web 管理界面 → 系统监控,应该能看到 GPU 信息了。
第四步:启用 GPU 硬件转码
4.1 配置 mediasrv 使用 GPU
编辑 mediasrv 配置文件:
sudo nano /usr/trim/etc/mediasrv.conf
确保配置如下(启用 GPU):
{
"cpu": {"allowDecoding": true},
"gpu": {"selectedGpuSequence": 1, "enable": true},
"cache": "/vol1/mediasrv.transcode"
}
enable: true — 启用 GPU 加速
selectedGpuSequence: 1 — 使用 GPU 序列(直通核显通常为 1)
4.2 重启 mediasrv 服务
sudo systemctl restart mediasrv
检查日志确认 GPU 被识别:
tail -20 /usr/trim/logs/mediasrv.log
成功输出:
[info] gpu in working, device_id 16017, device 'UHD Graphics 630', vendor 'Intel Corporation', card_path '/dev/dri/card1'
[info] gpu enable: true, selected sequence: 1
第五步:验证硬件转码
5.1 验证 VA-API
# 安装 vainfo(如未安装)
sudo apt install vainfo
# 检查 VA-API 支持
LIBVA_DRIVER_NAME=iHD vainfo --display drm --device /dev/dri/renderD128
应看到大量 encode/decode profile 支持:
vainfo: VA-API version: 1.21 (libva 2.21.0)
vainfo: Driver version: Intel iHD driver for Intel(R) Gen Graphics - 25.4.4
...
VAProfileH264Main : VAEntrypointEncSlice
VAProfileH264Main : VAEntrypointVLD
VAProfileHEVCMain : VAEntrypointEncSlice
VAProfileHEVCMain : VAEntrypointVLD
...
5.2 验证 ffmpeg 硬件转码
fNOS 自带的 ffmpeg(位于 /usr/bin/ffmpeg)已编译 VA-API 支持:
ffmpeg -version
# 应看到 --enable-vaapi 编译选项
测试硬件转码命令(从 HDR 源文件提取 10 秒进行转码测试):
ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi \
-i "你的视频文件.mkv" \
-t 10 -c:v h264_vaapi -c:a aac \
-f null -
如果能正常执行且 CPU 占用率远低于纯软解,说明硬件转码工作正常。
常见问题
Q1: /dev/dri/ 不存在或只有 card0
原因:i915 内核模块未正确加载。
排查步骤:
# 检查 i915 是否加载
lsmod | grep i915
# 查看内核日志中的错误
dmesg | grep -i i915
常见错误及修复:
错误 A:DC state mismatch
i915: DC state mismatch (0x0 -> 0x2) at intel_dmc_update_dc6_allowed_count
修复:创建/编辑 i915 modprobe 配置文件:
sudo nano /etc/modprobe.d/i915.conf
写入以下内容:
options i915 enable_dc=0 disable_power_well=0 disable_display=1
enable_dc=0 — 禁用 DC 状态,修复 DC state mismatch(关键参数)
disable_power_well=0 — 保留电源管理
disable_display=1 — 禁用显示输出(无头虚拟机推荐)
修改后需要重启虚拟机(i915 无法热重载):
sudo reboot
错误 B:unknown parameter 'enable_guc'
如果 fNOS 默认的 i915 配置包含 enable_guc=3,CoffeeLake 及更早的核显可能不支持 GuC 提交引擎。将其移除或修改。
Q2: mediasrv 日志显示 "couldn't get card path"
原因:i915 驱动未加载或 /dev/dri/ 暂时不可用(如 VM 刚启动还未就绪)。
修复:确认 i915 正常加载后重启 mediasrv:
sudo systemctl restart mediasrv
如果反复出现,检查 i915 配置(参考 Q1)。
Q3: resmon_service 显示 "can not probe trim dev"
这个消息通常出现在服务启动的早期阶段,不影响 GPU 监控。只要后续日志中出现 GPU ** name, vid:8086, pid:xxxx 就说明 GPU 已被正确识别。
Q4: fNOS 系统更新后 GPU 监控又失效了
原因:系统更新可能覆盖了修改过的 libigputop.so。
修复:重新执行第三步的 sed 替换命令,然后重启 resmon_service:
# 检查文件是否被更新
ls -la /usr/trim/lib/libigputop.so /usr/trim/lib/libigputop.so.bak
# 如果 .so 时间比 .bak 新,说明被更新了,重新替换
sudo sed -i 's/0000:00:02.0/0000:00:10.0/g' /usr/trim/lib/libigputop.so
sudo systemctl restart resmon_service
建议在 fNOS 更新后检查此文件。
原理总结
**─────────────────────────────────────────────────**
** PVE 宿主机 **
** **
** Intel 核显 (00:02.0) **
** ** **
** ** PCI Passthrough **
** ▼ **
** **──────────────────────────────────** **
** ** fNOS 虚拟机 ** **
** ** ** **
** ** bochs 虚拟显卡 → /dev/dri/card0 ** **
** ** Intel 核显 → /dev/dri/card1** ← 转码用 **
** ** renderD128 ** ← VA-API **
** ** ** **
** ** resmon_service ** **
** ** **─ libigputop.so ** **
** ** (硬编码 PCI 路径需要修补) ** **
** ** ** **
** ** mediasrv (v0.8.35) ** **
** ** **─ 读取 /dev/dri/card1 ** **
** ** **─ 通过 VA-API 硬件转码 ** **
** **──────────────────────────────────** **
**─────────────────────────────────────────────────**
核心修改点只有一处:libigputop.so 中的 PCI 路径从 0000:00:02.0 替换为直通核显的实际 PCI 地址。这是一个二进制文件中的 ASCII 字符串替换,不涉及重新编译。
免责声明
- 修改
libigputop.so 属于对 fNOS 系统文件的逆向修改,可能违反使用条款
- 此修改可能在 fNOS 系统更新后被覆盖,需要重新执行
- 操作前请务必备份原文件
- 作者不对因此操作导致的任何数据丢失或系统问题负责
本文基于 Proxmox VE + fNOS + Intel UHD Graphics 630 (8086:3E91) 环境测试编写。
如有问题欢迎交流讨论。