
一台带核显的小主机装好 PVE 之后你往往会被一个问题卡住既想让宿主机一直有 HDMI/DP 画面输出又想在这个虚拟化平台上跑一个日常能用的 Linux 桌面里面还要装 QQ、微信、谷歌浏览器、中文输入法偶尔再通过 Moonlight 串流到手机或另一块屏上。过去我试过的最常规做法是给虚拟机直通核显结果显示器经常变成黑屏宿主机这边直接失去图形输出。原因不难理解核显被整块交给了虚拟机物理 HDMI/DP 接口自然没有信号来源。后来我转向 PVE LXC 容器才慢慢把这条链路走通。标题里的“Ubuntu 26.04 桌面”可以理解成一套目标配置实际操作时换成当前稳定可用的 LTS 版本也完全成立。这个方案真正解决的不是跑分、不是单点功能而是把“宿主机显示、容器桌面、远程串流、常用办公软件”同时塞进一台机器里。核显 SR-IOV 让这四件事不再互相抢同一个出口。下面我会从问题、硬件、容器创建、图形输出、串流和常见坑这几个方面拆开讲。1. 先搞清楚这个方案到底在解决什么问题1.1 传统直通的困局显卡不是一块网卡显卡直通在虚拟化里看似简单把 PCIe 设备整体分配给一台虚拟机然后让那台虚拟机独占这块显卡。但核显的情况非常特殊。它不只是负责渲染还承担着物理显示输出、桌面合成、视频编解码等一堆任务。如果直接直通宿主机就失去了这个设备接在主板 HDMI/DP 接口上的显示器自然黑屏。搜索词里“pve amd 核显直通后hdmi黑屏”出现次数很高这恰好是新手最容易踩的坑。AMD 核显与内存控制器、显示输出单元耦合很深直通时就算把显卡设备放进虚拟机物理显示接口也不一定听话。Intel 核显的直通也有类似问题。很多人以为是自己配置错了实际上是方案选错了。1.2 SR-IOV 让核显从“独占设备”变成“可切分资源”SR-IOVSingle Root I/O Virtualization是一种 PCIe 设备的硬件虚拟化能力。它允许一个物理设备在硬件层面暴露多个虚拟功能VF每个 VF 都有自己的队列、资源和中断能力可以独立分配给不同的虚拟机或容器同时物理功能PF仍保留在宿主机上。对核显来说这意味着不必把整块 GPU 交出去。宿主机可以继续使用 PF 做物理显示输出而 LXC 容器可以拿到一个 VF运行自己的桌面合成器再用串流协议把画面送到其他设备。这才是“HDMI/DP 输出”和“容器桌面”共存的底层基础。不过要注意核显 SR-IOV 并不是通用功能很多消费级核显并不可用或者只能在特定内核版本和特定驱动参数下才能开启。不要头脑一热就开始装系统先确认硬件再谈配置。1.3 LXC 相比 VM 的关键差异共享内核但隔离设备LXC 不是虚拟机它和宿主机共享同一个 Linux 内核主要靠 cgroup、namespace 和 device cgroup 做进程与设备隔离。这个区别在 GPU 场景非常关键。传统虚拟机需要提供完整的虚拟化硬件然后安装自己的显卡驱动PCIe 直通要处理 IOMMU 分组、中断、ROM 等复杂问题。LXC 容器则可以直接访问宿主机已经存在的设备节点只要在配置文件里把设备映射进容器并在容器内调整权限即可。优点是轻量、启动快、配置灵活代价是容器不能有自己的独立内核所有 GPU 驱动、固件、内核参数都必须由宿主机提供。所以在这个方案里真正影响成败的不是容器里装了什么桌面环境而是宿主机内核和驱动是否已经把 SR-IOV 能力准备好。2. 动手前先摸清自己的硬件底线2.1 核显 SR-IOV 不是所有平台都支持一定要把这句话放在最前面不是所有带核显的 CPU 都能做 SR-IOV。必须同时满足 CPU、核显、主板、BIOS、内核和驱动多方面的条件。Intel 平台的核显 SR-IOV 支持在不同代际之间差异很大。某些较新的核显/Arc 系列在特定内核和驱动下可以启用 GPU 分区过去还有过 GVT-g 这类方案但随着内核演进实现方式也在变化。AMD 平台的消费级核显对 PCIe SR-IOV 的支持同样不是默认开启而且文档少、坑多需要反复查证。更稳妥的做法是先确定自己的 CPU 型号和核显架构再去查当前 PVE 内核下有没有对应的 SR-IOV 支持方式。不要因为看到网上有人成功就以为复制配置一定能成功。硬件不同结果完全不同。2.2 主板、BIOS 和内核的三重配合BIOS 层面需要开启 VT-dIntel或 AMD-ViAMD并且开启 SR-IOV 相关选项。有些主板把 SR-IOV 开关藏在北桥或 PCIe 设置里名字可能是 “SR-IOV”、“IOMMU” 或 “Virtualization Technology”。如果找不到要先去确认主板说明书。内核层面PVE 使用的内核必须包含对应的显卡驱动模块。Intel 核显常用的是 i915AMD 核显常用的是 amdgpu。如果驱动版本太老或者内核没有开启某些实验性参数SR-IOV 虚拟功能就不会暴露。这里不建议直接抄网上那些内核参数。因为同一驱动在不同版本上的参数名和默认值都可能发生变化某个参数在新内核里可能已经失效。最靠谱的办法是启动后查看dmesg和/sys/bus/pci/devices/*/sriov_totalvfs之类的接口确认设备是否真的支持 SR-IOV再决定要不要加参数。2.3 在 PVE 上完成基础 IOMMU 检查进入 PVE 后先用 SSH 连到宿主机做几个基础检查cat /proc/cmdline看内核启动参数里是否包含intel_iommuon或amd_iommuon。如果没有说明 IOMMU 还没开启需要进 BIOS 修改并重新启动。dmesg | grep -i iommu看日志中是否出现 IOMMU enabled 之类的信息。lspci | grep VGA找到核显设备例如00:02.0 VGA compatible controller: Intel Corporation ...。然后看它的 SR-IOV 能力lspci -s 00:02.0 -vvv如果输出里有Single Root I/O Virtualization (SR-IOV)的 Capability说明硬件层面已经支持。如果完全没有这一项后面的容器配置做得再漂亮也白搭。3. 创建 LXC 容器把 Ubuntu 桌面装进一个轻量环境3.1 先决定容器类型特权容器还是非特权容器在 PVE 里创建 LXC 容器时会遇到一个选择特权容器还是非特权容器。简单来说非特权容器更安全但访问 GPU 设备节点会麻烦不少特权容器更容易把自己的设备直接映射进容器但风险也更高。如果是第一次验证这个方案建议先用特权容器把 GPU 和桌面跑通确认没有问题后再尝试用非特权方式复现。不要一上来就在生产环境长期使用特权容器尤其是这个容器还要跑 GUI 应用的时候。创建命令在 PVE 里一般通过图形界面或pct create完成。系统模板选择带 Debian 或 Ubuntu 的 CT 模板后续容器内再安装桌面环境。如果你的 PVE 模板列表里没有 Ubuntu 26.04就选择当前能获取到的最新 LTS 模板比如 24.04然后正常 apt 更新即可。3.2 安装桌面与应用从桌面环境到中文输入法进入容器后第一步是安装 Ubuntu 桌面。如果想要轻量一些可以装 Xfce 或 LXQt如果想要接近原版 Ubuntu 的观感可以装 GNOME 桌面。命令大致是apt update apt install -y xubuntu-desktop或者apt install -y ubuntu-desktop后者依赖包会非常多建议根据自己的内存和磁盘来定。容器里跑桌面不像虚拟机那样有独立显卡 BIOS桌面合成器能不能流畅运行很依赖宿主机提供的 GPU 能力。接下来是应用层。QQ、微信这些即时通讯工具都有 Linux 版本有的通过官方 deb 包提供有的通过 Flatpak 或 AppImage 方式运行。谷歌浏览器可以直接下载 deb 包安装sudo apt install -y ./google-chrome-stable_current_amd64.deb视频播放器建议安装 MPVsudo apt install -y mpv中文输入法推荐用 fcitx5 体系sudo apt install -y fcitx5 fcitx5-chinese-addons fcitx5-config-qt如果你特别习惯搜狗输入法也可以装搜狗拼音 Linux 版但它依赖的库更多在容器里的稳定性需要额外验证。建议先用 fcitx5 把你的日常输入跑稳再考虑要不要替换。3.3 让容器访问核显设备设备节点与权限映射这是整个方案里最核心的一步。PVE 创建 LXC 后GPU 设备并不会自动出现在容器里需要手动把设备节点映射进去。常规情况下GPU 设备通常在宿主机上表现为/dev/dri/card0 /dev/dri/renderD128如果 SR-IOV 开启就会有多个 renderD 节点例如renderD128、renderD129、renderD130等。每个 VF 可能对应一个或多个节点。在容器配置文件中常见做法是添加设备映射。PVE 的 LXC 配置文件一般在/etc/pve/lxc/容器ID.conf。示例结构如下lxc.cgroup2.devices.allow: c 226:0 rwm lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,createfile lxc.mount.entry: /dev/dri/card0 dev/dri/card0 none bind,optional,createfile注意226是 DRM 设备的主设备号0是次设备号实际要以ls -l /dev/dri看到的为准。VF 对应的设备和 PF 不同不要把 PF 和 VF 搞混否则又会回到独占问题。这里需要强调一点不同 PVE 版本、不同内核、不同 lxcfs 版本下设备 cgroup 的配置写法会有变化。上面的代码只是常见写法不一定直接适用。最安全的方式是先查看 PVE 官方文档或论坛中与你当前版本匹配的 LXC GPU 映射方法先在测试容器里验证再应用到正式环境。如果你觉得手动编辑配置文件有风险也可以先在 PVE 图形界面中尝试给容器添加设备保存后再查看配置文件里的真实写法这样能减少拼写错误。3.4 单机验证容器里先看到渲染节点容器启动后进入容器ls -l /dev/dri如果能看到renderD128或类似节点说明设备映射已经生效。如果什么都看不到不要急着继续装软件先回宿主机检查设备和容器配置。看到设备之后再验证硬件加速sudo apt install -y mesa-utils vainfo glxinfo | grep OpenGL renderer vainfo如果输出里出现了正确的显卡型号说明容器已经拿到了 GPU 能力。vainfo能列出支持的编码/解码格式这对后面的 Moonlight 串流非常重要。这一步是整个流程的分水岭。只有容器里能看到渲染节点后续的桌面流畅度、视频播放硬件解码、串流编码才有意义。4. 让画面从两种路径同时出来HDMI/DP 与 Moonlight4.1 物理输出和虚拟显示如何协商很多人看到“HDMI/DP 输出”和“LXC 跑桌面”放在一起潜意识里会以为是让容器里的桌面直接显示在物理显示器上。从实际工程经验看这种直接显示很难做因为物理 HDMI/DP 输出一般由 PF 驱动而容器拿到的是 VF。即使勉强通过某种方式绑定也会受到硬件、驱动和显示管线的多重限制。更正确的理解是宿主机保持物理显示输出使用 PF 驱动显示器容器使用 VF 渲染自己的桌面再通过 Moonlight 串流把画面送到另一块屏幕。这样一来物理输出和远程输出就共存了。如果你需要的是“容器桌面直接出现在客厅电视上”那大概率需要额外的显示输出管理技术甚至需要核显有多个显示控制器而这超出了大多数消费级硬件的支持范围。先想清楚自己到底要哪条路径再动手配置。4.2 用 Moonlight 串流容器桌面Sunshine 服务端与客户端Moonlight 本身是一个客户端它最初是为了连接 NVIDIA 的 GameStream 服务后来也支持开源服务端 Sunshine。在 Linux 桌面场景里通常是在容器内安装 Sunshine把整个桌面或某个应用作为串流目标然后用 Moonlight 客户端连接。在容器里安装 Sunshine 之前要确保容器内已经有可用的硬件编码能力。如果你是 Intel 核显的 VF通常通过 VA-API 提供编码如果是 AMD 核显也要确认对应的编码器驱动在容器内可用。可以先运行vainfo看看输出里有没有H264、HEVC编码支持。安装完 Sunshine 后需要配置串流分辨率、帧率和码率。第一次调试建议这样分辨率设置为 1920x1080不要直接上 4K。帧率先设为 60fps如果网络状况不好再降到 30fps。码率可以先用 20 Mbps 左右再根据实际流畅度调整。然后启动 Moonlight 客户端完成 PIN 码配对就能把容器桌面串流到手机、平板或另一台电脑上。这种做法最大的好处是串流过程用到了 GPU 的硬件编码器而这些编码器资源来自 VF不会影响宿主机原本的显示输出和桌面合成。4.3 中文输入法和常用 IM 窗口的体验调整即使 GPU 和串流都通了桌面体验还会败在输入法切换和窗口焦点这些看似不起眼的细节上。fcitx5 安装后需要确保相关环境变量在桌面会话中生效。常见配置export GTK_IM_MODULEfcitx export QT_IM_MODULEfcitx export XMODIFIERSimfcitx如果你使用的是 Wayland 会话还需要确认 fcitx5 在启动时自动运行。可以直接在 autostart 里添加一个 desktop 文件这样登录进桌面后输入法就会出现在托盘上。QQ 和微信的 Linux 版对中文输入法的支持经常不完整。有的应用用的是 GTK有的用的是 Qt不同工具包对 IM 模块的读取逻辑不一样。如果发现输入法在某个应用里没有响应可以尝试把输入法集成方式改成fcitx或者调整应用的启动环境变量。这个步骤没有统一答案只能一个个应用去适配但总比用网页版输入体验好得多。5. 常见问题排查链路从黑屏到无声5.1 黑屏/无信号优先查宿主机输出和设备绑定如果调整配置后 HDMI/DP 黑屏先判断是宿主机黑屏还是容器内桌面黑屏。多数情况下是宿主机显示输出被占用或设备绑定错误。解决方案很简单拔掉显示器前先通过 SSH 连到宿主机查看dmesg | tail -n 50 dmesg | grep -i drm看看 DRM 子系统的输出是不是被某个设备抢占。如果是因为之前直通错误导致核显整体被丢给虚拟机那就要优先恢复 PF 与宿主机的绑定关系。而 SR-IOV 场景下宿主机使用的是 PF容器使用的是 VF理论上不应该出现宿主机黑屏。如果出现了大概率是内核驱动没加载好或者 PF 被误映射进了容器。5.2 容器内没有 GPU 节点优先查权限和共享容器里看不到/dev/dri/renderD*最常见的三个原因容器配置文件里没有添加设备映射。设备节点的主设备号和次设备号与实际不符。容器是以非特权模式运行设备 cgroup 权限没有放行。排查顺序建议是这样pct status CTID ls -l /dev/dri/renderD* cat /etc/pve/lxc/CTID.conf如果宿主机里能看到多个 renderD 节点但要确认哪些是 VF哪些是 PF。不要把 PF 塞进容器否则会重新制造独占问题。如果容器是非特权模式还要检查用户命名空间是否把宿主机的 GID 映射到了容器内合适的位置。这部分很容易让人头疼建议第一次先用特权容器验证跑通后再做安全强化。5.3 声音、输入法、串流延迟的常见坑音频在 LXC 容器里是一个绕不过去的麻烦。桌面应用要发声通常需要让容器访问宿主机的 PulseAudio 或 PipeWire 服务。比较常见的方式是把宿主机的 PulseAudio socket 挂载进容器并设置容器内环境变量指向这个 socket。示例思路是lxc.mount.entry: /run/user/1000/pulse run/user/1000/pulse none bind,optional,createdir但这个方法依赖用户 ID、会话权限以及宿主机音频服务是否正常运行每次登录状态变化都可能导致容器内音频失联。如果你对音频延迟要求不高可以先跳过后续再专门处理。串流延迟则优先检查编码器、分辨率和供电策略。不要一开始就用 4K 60建议先用 1080p 验证再逐步提高。如果延迟很高先看是网络问题还是编码问题。可以在 Sunshine 日志里查看编码耗时如果编码时间很长说明容器访问 GPU 的路径不对或者编码器驱动没生效。6. 这种方案的边界适合什么人不适合什么人6.1 适合单主机整合场景这套方案最适合的场景是像一台 NUC 或 mini 主机这样的设备。你希望它既是 PVE 宿主机又是日常桌面机偶尔还能在手机或另一块屏幕上串流出来用。因为容器比虚拟机轻量启动快资源占用低所以很适合常驻运行一个 Ubuntu 桌面里面挂着 QQ、微信、浏览器和视频播放器。如果你只是想学习 GPU 虚拟化、设备映射、容器权限管理这也是一个很好的实验项目。它能帮助你把“直通”和“共享”这两个概念彻底分开。6.2 不适合追求兼容和性能极致的场景这套方案不适合以下情况必须使用 NVIDIA 独显并依赖官方驱动。LXC 容器内跑 NVIDIA 桌面驱动的兼容性很麻烦SR-IOV 在消费级 NVIDIA 显卡上也不普及。需要玩大型 3D 游戏。VF 的性能有限驱动匹配要求高即使能跑起来也没法和物理机相比。需要一个生产级、官方认证的 GPU 虚拟化方案。PVE 的 LXC SR-IOV 更像是一个玩家级或实验级方案并不适合关键生产业务。如果你只是想要一个稳定运行的 Linux 桌面最好的选择永远是物理机直接装 Ubuntu不要套 PVE。虚拟化的价值是灵活和隔离但代价是性能和兼容性。6.3 从一次性跑通到长期维护的建议当整套环境过了“能跑”这个阶段长期维护才是真正的挑战。因为你可能会遇到PVE 或内核升级后设备节点顺序变化。LXC 配置文件格式调整。宿主机驱动更新后VF 数量或映射方式改变。容器内 Ubuntu 大版本升级后桌面会话和输入法配置丢失。所以建议从一开始就记录你当前的版本信息至少包括PVE 版本宿主机内核版本Ubuntu 发行版版本设备节点 major/minor 号容器配置文件里的关键 mount 和 cgroup 行把这些内容写到文本里或放到 PVE 备份中。下次遇到问题能少走很多弯路。另外一个务实建议是开机自启不要一口气全开。让容器启动、Sunshine 启动、桌面环境启动按顺序来确认每一步都成功再把自启加上。否则哪天开机后只有一个黑屏连排查都无从下手。从一次完整的高质量长文来看这套方案的核心判断其实很简单它让 PVE 宿主机和容器在“同一个核显”上各取所需把过去“直通必黑屏”的悲剧变成“PF 和 VF 各司其职”的协作。如果你也想在 PVE 上同时拥有物理显示和容器桌面先别急着安装全家桶第一步永远是让容器里出现一个真实的/dev/dri/renderD*节点。只有这一步稳定了后面的 QQ、微信、Moonlight 才谈得上真正好用。