资讯动态

PCIe直通与SR-IOV深度拆解:从I/O虚拟化原理到实战选型

发布时间:2026/10/23 3:53:09 来源:尧图企业网站定制
最近给一个虚拟化平台调网络性能折腾了大半个星期最后发现瓶颈不在虚拟机配置也不在应用层而是卡在了I/O虚拟化这条看不见的路径上。当时两台宿主机的万兆网卡一台用传统的软件虚拟交换机一台直接做PCIe直通同一份压测脚本吞吐量差了快一倍。后来又试了SR-IOV效果又是另一番光景。这事儿让我意识到很多人把直通和SR-IOV当成“性能优化开关”来用却不太清楚这两种技术到底动了什么手脚、各自适合什么场景。所以这篇就把PCIe直通和SR-IOV从底层逻辑到实战选型完整拆一遍给正在搞虚拟化、超融合或者云平台底层的人做个参考。先说结论PCIe直通和SR-IOV的根本区别不在于“性能谁更高”而在于它们对硬件资源的划分方式不同——一个是把整台物理设备独占给一台虚拟机另一个是把一个物理函数拆成多个可独立使用的虚拟函数。这个差异决定了它们的适用场景、隔离程度、迁移难度甚至排障思路完全不一样。1. 事情要从I/O路径讲起虚拟化卡住性能的那道坎1.1 软件模拟设备为什么注定不快虚拟机的CPU和内存虚拟化经过多年迭代性能损耗已经压得很低。但I/O不一样。一块物理网卡收到数据包需要触发中断把数据通过DMA写入内存再通知驱动处理。整个过程在物理机上由硬件直接完成轻描淡写到了虚拟机里每次I/O操作都要经过虚拟设备模型这一层“翻译”问题就来了。传统软件虚拟网络设备的工作方式是宿主机上的QEMU或者类似Hypervisor软件模拟一个网卡设备。虚拟机里的驱动往这个模拟网卡写寄存器触发VM-Exit陷入到宿主内核宿主要截获这次MMIO访问解析成对应的设备操作再把它转交给一块真实的物理网卡。数据从物理网卡收进来之后往往还要经过宿主机协议栈、虚拟交换机、再拷贝到客户机内存涉及多次上下文切换和内存拷贝。客户机里每收发一个包CPU的开销可能是物理机的数倍甚至更多。性能敏感型业务在这种路径下会死得很难看延迟抖动大小包吞吐惨不忍睹多队列网卡的RSS接收侧扩展也无法穿透虚拟层直达客户机。所以大家开始寻找“更硬”的路径——让客户机直接接触真实硬件。这就走到了PCIe直通和SR-IOV面前。1.2 直通与SR-IOV各自的解题位置用一个不太严谨但好记的类比传统软件模拟像“样板房”——看得到效果但没有实际使用权限每次使用都要通过物业Hypervisor协调PCIe直通像“直接包下一整层写字楼”——客户机拿到钥匙空间独享可代价是别人不能再用SR-IOV则像“房东把一个物理单元分割成多个独立套房”——每个套房有独立门牌和水电表房东PF统一维护大楼租户VF互不干扰。从I/O路径来看PCIe直通虚拟机的设备驱动直接操作物理设备的MMIO寄存器数据面的DMA路径由IOMMU做地址翻译和保护Hypervisor基本退出数据通路。SR-IOV物理设备内部把队列、缓冲区、中断等资源划分成多个VF每个VF看起来就是一张独立的PCIe网卡可以直接分配给不同虚拟机。两者都大大缩短了虚拟化I/O路径但彻底程度不同。直通是“零分享”SR-IOV是“硬件级共享”。理解了这一点后面的所有配置和选型才谈得上有据可依。2. 直通到底“通”在哪里从IOMMU到VFIO的完整链路2.1 IOMMU如何接管DMA与中断专线式地址翻译PCIe直通最核心的底层支撑是IOMMU。在Intel平台上通常叫VT-d在AMD平台上叫AMD-Vi。它做的事情本质上是给每个PCIe设备建立一张“DMA地址通行证”把设备发起的DMA请求从物理地址空间重新映射到宿主机真实的物理地址。为什么要这么绕因为普通PCIe设备的DMA能力是“物理地址直达”的它想读写哪个物理地址就写哪个物理地址。如果没有IOMMU让虚拟机直接操作物理设备这个设备就可以任意读写整台宿主机的物理内存——那等于把宿主机扒光了扔给客户机。IOMMU存在的意义就是把设备的这种“无法无天”能力约束起来。具体工作过程大致是设备发起DMA请求时IOMMU根据请求者ID总线号、设备号、功能号即BDF查一张上下文表Context Table找到它所属的域Domain。域里维护着一张页表映射的其实是客户机的物理地址到宿主机物理地址之间的转换关系。设备自以为在写客户机的物理地址实际经过IOMMU翻译后写到了宿主机里分配给那块虚拟机的真实内存。翻译过程由硬件完成性能损耗极低。中断路径类似。PCIe设备发中断如果是传统INTx或者MSI/MSI-X中断请求会经过中断重映射Interrupt Remapping单元。IOMMU里的中断重映射表会把设备指定的中断向量重定向到宿主机上真正对应的vCPU中断号这样直通设备的中断才能准确投递到客户机指定的vCPU上。提示直通模式的性能之所以接近物理机不是因为Hypervisor“放水”而是IOMMU把事情从软件搬到了硬件。没有IOMMU的直通是不可接受的等于拿主机安全换性能。2.2 为什么现代环境用vfio-pci而不是pci-stub早期Linux做PCIe直通有人用pci-stub或者直接让设备脱离驱动把物理设备留给虚拟机。但这种方式太“裸”了它只做到了“宿主机驱动别碰设备”却没有提供DMA隔离和中断重映射的用户态接口客户机拿到的设备直接用物理DMA地址没问题才怪。vfio-pci是更完整的安全模型。它的思路是把物理设备暴露给用户态进程比如QEMU之后通过VFIO API在用户态配置IOMMU domain、映射客户机内存、设置中断重映射。设备分配、DMA映射、中断路由都由VFIO框架统一管理天然支持MSI/MSI-X直投还支持PCIe的ATS/PASID这些高级特性。简单说pci-stub只是“让设备闲置”vfio-pci是“把设备安全地交给某个用户态程序”。现在的KVM/QEMU直通方案基本都走vfio-pci。2.3 一次最小可用的PCIe直通配置记录这里记录一套典型的网卡直通配置过程也给后面排障章节留个引子。宿主机BIOS里打开VT-d/AMD-Vi和SR-IOV相关的开关。不同厂商BIOS叫法不一样常见的有“VT-d”“AMD IOMMU”“SR-IOV”字样。修改内核启动参数在GRUB里追加intel_iommuon iommupt # 如果AMD平台则是amd_iommuon iommupt其中iommupt表示只有在直通设备时启用IOMMU翻译平时普通设备走identity mapping降低总体开销。查看IOMMU分组确认要直通的设备是否独立成组find /sys/kernel/iommu_groups/ -maxdepth 2 -type l | grep 0000:3b:00.0把设备绑定到vfio-pcimodprobe vfio-pci echo 0000:3b:00.0 /sys/bus/pci/drivers/vfio-pci/bind也可以开机时通过内核参数预留vfio-pci.ids15b3:1015启动QEMU/KVM时附加设备-device vfio-pci,host0000:3b:00.0这套配置跑起来之后客户机里看到的就是一块不折不扣的物理网卡驱动按物理网卡的方式加载。提示显卡直通比网卡复杂通常还需要准备单独的VBIOS ROM文件romfilexxx.rom在UEFI客户机里可能还要处理GOP和显存映射问题。如果一开始用显卡练手建议先拿一张不重要的卡别拿唯一的显示输出卡试错。直通的代价同样直接整块设备被一台虚拟机独占其他虚拟机用不了物理设备的热迁移基本不可能因为设备状态跟着物理硬件走迁移等于重新分配硬件。所以直通适合“专用型”负载比如AI推理要用GPU、数据库要低延迟NVMe盘、网络功能虚拟化要独占网卡队列而不是高密度多租户共享场景。3. SR-IOV不是“砍一刀”一个物理函数如何剪出多个独立可用的VF3.1 PF/VF模型与PCIe配置空间里的“虚拟化约定”SR-IOV的全称是Single Root I/O Virtualization在PCIe规范里定义了一组能力和行为约定让一个物理PCIe设备以硬件方式呈现多个可独立使用的虚拟PCIe函数。设备里至少有一个物理函数PF管理整块设备资源。PF通过PCIe配置空间里的SR-IOV扩展能力结构宣告自己支持虚拟化并暴露若干配置项比如TotalVFs设备最多能创建的VF总数。NumVFs当前需要激活的VF数量。First VF Offset第一个VF相对PF的位置关系。VF Stride两个VF之间的地址间隔。操作系统读取这些字段就知道如何枚举和分配VF的总线号设备号。创建VF时设备内部会为每个VF划分独立的硬件资源包括收发队列、DMA区域、中断条目等。每个VF在PCIe总线上被识别为一个完整的PCIe函数有自己独立的配置空间子集、自己的BDF、自己的BAR空间。看一张典型四口网卡的枚举结果# 启用8个VF后lspci的输出类似 # 03:00.0 Ethernet controller: PF # 03:00.1 Ethernet controller: VF0 # 03:00.2 Ethernet controller: VF1 # ... # 03:00.8 Ethernet controller: VF7对客户机来说一个VF就是一张普通网卡驱动该加载什么加载什么完全不知道背后还有PF和其他VF存在。3.2 VF在宿主机上如何被枚举和绑定在Linux上启用SR-IOV通常需要物理网卡支持并且尽量使用较新的内核。操作路径在/sys/bus/pci下先检查物理网卡是否带SR-IOV能力lspci -vvv -s 03:00.0 | grep -i sriov # 输出类似 # Capabilities: [150 v1] Single Root I/O Virtualization (SR-IOV)启用8个VFecho 8 /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs创建出来的VF默认挂在某个驱动下如果想把它直通给虚拟机就需要先把VF绑定到vfio-pciecho 0000:03:00.1 /sys/bus/pci/drivers/vfio-pci/bind对于要批量处理的场景最好配合udev规则或者脚本在开机时自动设置# 示例udev规则开机把VF绑定到vfio-pci ACTIONadd, SUBSYSTEMpci, ATTR{vendor}15b3, ATTR{device}1015, DRIVERixgbevf, RUN/bin/sh -c echo $kernel /sys/bus/pci/drivers/vfio-pci/bind提示不要在宿主机上把VF和PF绑定到同一个驱动来“测试网卡性能”因为一旦PF驱动管理VF就会限制VF的用途。如果希望VF既能在宿主机上用又能直通给虚拟机需要看具体网卡驱动是否支持把部分VF上下发到不同的驱动。3.3 SR-IOV在实际业务中的吞吐实测体会我在一次虚拟化网络改造中给一台双路服务器插了两张万兆网卡开了16个VF分给16台虚拟机。同样跑多流iperf测试结果比之前每VM共享一张物理网卡的方案要好总吞吐接近两张卡的线速总和各VM之间的抖动量级明显下降。更重要的是客户机里的收包CPU占用率比软件虚拟交换低了很多原因是多队列直接分配到vCPU不再经过宿主机的软中断转发。不过要注意SR-IOV的“硬件级共享”不代表某些VF的突发流量不会影响同PF下的其他VF。网卡内部的总线带宽、缓存、PCIe链路带宽是共享资源。压测中遇到过单个VF打满线速时同一PF下另一个VF的延迟略有上升。所以在规划资源时要留有余量别看到8个VF就觉得网卡“被切成8份”每个都能跑满单端口线速。4. 直通和SR-IOV该怎么选一张表说明白4.1 性能、隔离、迁移、复杂度四项权衡直通和SR-IOV不是非此即彼更多时候是“工作负载决定选型”。四个维度区分最关键维度PCIe直通SR-IOV性能损耗接近原生个别场景几乎无损耗接近原生但有少量共享资源竞争设备共享一块物理设备只能给一台虚拟机一个物理设备可拆出多个VF分给多台VM隔离性绝对隔离独占物理资源和DMA通道硬件级隔离但仍共享PF内的总线和缓存热迁移基本不支持物理设备状态无法随VM迁移比直通灵活但带VF的热迁移仍需平台和设备配合配置复杂度较低主要处理IOMMU和绑定较高要处理PF/VF关系、设备插件、调度策略适用负载GPU、AI推理、专用加速卡、低延迟NVMe高密度虚拟网络、多租户NFV、DPDK、云平台网卡池化4.2 典型场景对照GPU与网卡两条线举两条最典型的主线GPU/AI负载。一般建议用直通尤其是一张卡只服务一个推理任务、需要完整显存和固定拓扑的场景。虽然现在也有硬件的GPU虚拟化方案但它们要么有额外的授权限制要么依赖厂商的虚拟化驱动复杂度远超一张卡直通过去的开箱即用。SR-IOV在这条线上比较少不做资源分割还好如果强行把一个GPU切成多个VF性能和安全性都有隐患。高吞吐网络/NFV。这种场景追求的是“端口密度 多租户隔离”推荐SR-IOV而不是直通。因为每一张物理网卡直通出去只能服务一个业务端口利用率太低用SR-IOV可以把一张40G/100G网卡切成多个VF分给几十台虚拟机配合DPDK在客户机里做用户态收包延迟和吞吐都能打。另一个原因是SR-IOV的VF在重启虚拟机或重建虚拟机时可以重新绑定到新的虚拟机上整体调度灵活度高于直通。还有一个真实约束IOMMU分组。每个IOMMU group里的一整组设备必须整体直通或整体保留没法把一个组里的某个设备单独分出去。很多双口网卡的两个物理口在同一个IOMMU group里直通的时候要么两个口一起给同一台VM要么就不给。SR-IOV模式下VF通常能跨过这个限制因为VF本质上是同一PF派生出的独立函数分组约束相对宽松。这是我在某次直通双口网卡时的实际教训插曲放在排障部分讲。5. 排障实录IOMMU分组、ACS、显卡黑屏、中断发偏5.1 直通双口网卡时IOMMU Group把两个口绑死某次要把一张双口万兆网卡的两个物理口分别直通给两台不同的虚拟机结果折腾了半天第二个口始终起不来。查/sys/kernel/iommu_groups/发现两个物理口挂在同一个group下。IOMMU的分组规则是只要PCIe拓扑里这些设备之间没有做ACSAccess Control Services隔离它们就会被视为“同一安全域”必须整体操作。两个口挂在同一个PCIe桥下又没有独立的ACS能力就变成了一荣俱荣、一损俱损。解决办法有几个方向看BIOS里有没有PCIe ACS开关或是平台自带隔离的功能。如果有打开后会让分组更细。对特殊设备有时可以通过内核模块参数跳过ACS检查比如某些平台上给vfio-pci加disable_acs之类的参数。但生产环境不建议这相当于放弃设备间互访的安全隔离。最实用的替代方案干脆改用SR-IOV把一张卡拆成多个VF分发出去绕开IOMMU group的“整体直通”约束。我最后就是这么落地的。提示凡是直通后设备“半死不活”、dmesg里频繁出现DMA错误或地址翻译异常的第一件事就是查IOMMU分组和设备拓扑不要先去怀疑驱动十有八九是分组没满足。5.2 显卡直通黑屏的经典环节显卡直通翻车概率极高最常见的是客户机启动后黑屏。造成原因很多首当其冲的是VBIOS/ROM问题设备默认的Option ROM不适合UEFI方式启动的客户机或者被宿主机占用的VBIOS无法被客户机初始化。处理顺序在QEMU里显式指定显卡ROM文件-device vfio-pci,host01:00.0,romfilevbios_gpu.rom加x-vgaon把设备当成VGA设备这步对老式非UEFI启动很关键。-device vfio-pci,host01:00.0,x-vgaon检查宿主机内核是否接管了显卡输出必要时给启动参数加videoefifb:off或nomodeset避免宿主机framebuffer与客户机抢占设备。还有一个容易忽略的坑直通显卡的虚拟机内存要预留足够并且最好开启UEFI引导。某些显卡在UEFI模式下需要独立的GOP驱动而BIOS模式下没有GOP直通后可能开机自检都过不去。我建议凡做显卡直通一律用UEFI客户机省掉很多玄学问题。5.3 中断发偏导致客户机收包CPU 100%有次SR-IOV的VF进了虚拟机业务量一上来客户机里某颗vCPU的软中断占用直接打到100%其他vCPU闲着。用mpstat -P ALL看发现所有网络中断都挤在同一个vCPU上。这在物理机上通常是多队列网卡的RSS把中断均分了但VF在虚拟环境里传递到客户机后中断目标要经过IOMMU中断重映射如果宿主机侧把中断固定到了一个CPU就会造成“中断发偏”。排查动作在宿主机上查看该设备中断的smp_affinitycat /proc/irq/44/smp_affinity_list如果被钉在单个CPU手动设置亲和性echo 0-3 /proc/irq/44/smp_affinity_list同时确认宿主机的irqbalance没有自作主张把所有设备中断收敛到某几个核心上。做性能敏感场景时宁可关掉irqbalance手动按NUMA拓扑绑定vCPU和中断也别让它随机调度。这类问题在直通场景下稍微少见因为直通设备的中断完全交付给客户机由客户机自己的驱动和亲和性决定SR-IOV多了VF这一层宿主机对中断的干预空间更大排障时不要只看客户机内部。5.4 AER错误与链路复位问题PCIe直通设备在虚拟机重启、设备热插拔、VF重配时偶尔会看到pcieport ... AER: Corrected error received: ...这类错误一般不代表设备坏了而是PCIe链路状态在复位过程中发生了变化。处理上先看是不是持续错误用lspci -vvv看设备状态再用dmesg确认是否是链路训练或带宽协商问题。如果只是偶发的Corrected错误忽略即可如果反复出现Uncorrected错误就要考虑更新设备固件和宿主机BIOS。修改PCIe链路带宽和速率设置比如把Gen3降为Gen2观察是否稳定。调整内核参数pcirealloc让系统重新分配桥后的地址空间解决资源不足导致的复位失败。很多AER错误在排障时被误判为设备质量问题实际上就是PCIe拓扑规划或固件组合的问题。建议直通设备集中跑一段时间把dmesg里的AER记录抓全再判断。6. 往容器和云平台走SR-IOV在编排层的落地思路SR-IOV不只服务虚拟机在容器化环境里也一样吃香。Kubernetes集群里要把物理网的转发延迟降到接近物理机比较常见的做法就是把PF上拆出的VF当作“可分配设备”暴露出来每个容器宣称自己独占一个VF数据面直接走用户态DPDK或者AF_XDP绕开容器网络插件这一层。这与虚拟机场景的底层机制完全一致——容器里看VF就是一张真实的PCIe网卡只是资源调度交给了容器编排平台。落地的几个关键点每个节点上要保证PF对应的VF数量足够且启动参数预留vfio-pci.ids。使用设备插件机制上报VF资源例如把vendor-id/device-id类型的设备资源上报给调度器Pod调度时按资源名分配VF。容器挂载VF时宿主机侧同样要先完成VF到vfio-pci的绑定容器内才能通过VFIO用户态接口操作设备。归根到底不管上层是虚拟机还是容器底层还是那套PCIe能力、IOMMU翻译、VFIO接口的组合。把直通和SR-IOV的原理吃透上层的编排只是套壳。我在实际项目中吃过不少亏最值钱的教训是别一上来就问“用直通还是SR-IOV”先问业务要什么。业务要独占某块加速卡低延迟且不能容忍共享抖动就用直通业务要高密度的网卡资源、多租户隔离、灵活调度就用SR-IOV。搞清I/O路径上的那点“硬件分工”差异后面排障和设计心里会踏实很多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑