当前位置: 首页 > news >正文

Virtio 驱动初始化数据收发流程详解

Virtio 驱动核心流程详解

一、整体架构概览

virtqueue
中断/通知
sk_buff
数据
前端驱动
后端设备
协议栈

二、初始化流程

1. 核心步骤
Linux KernelVirtio DriverVirtio Device设备发现(PCI/MMIO)读取设备ID特性协商(feature bits)配置virtqueues分配virtnet_info结构创建net_device对象设置DRIVER_OK状态注册网络设备预填充RX缓冲区Linux KernelVirtio DriverVirtio Device
2. 关键函数调用栈
virtnet_probe()├─ virtio_cread_feature()       // 特性协商├─ alloc_etherdev_mq()          // 创建net_device├─ virtnet_find_vqs()           // 初始化virtqueues│   ├─ virtio_find_vqs()│   └─ virtqueue_set_affinity()├─ register_netdev()            // 注册网络设备└─ virtnet_alloc_rx_buffers()   // 预填充接收缓冲区

三、数据发送流程(TX)

1. 核心流程
Network StackVirtio DriverVirtio BackendPhysical NICndo_start_xmit(skb)映射DMA区域添加描述符到TX virtqueuevirtqueue_kick()通知发送网络数据发送完成更新used ring发送中断通知处理TX完成中断回收sk_buff解除DMA映射Network StackVirtio DriverVirtio BackendPhysical NIC
2. 关键函数
// 发送入口
start_xmit(struct sk_buff *skb)├─ skb_to_sgvec()               // 创建分散/聚集列表├─ virtqueue_add_outbuf()       // 添加发送描述符└─ virtqueue_kick()             // 通知设备// 发送完成处理
skb_xmit_done(struct virtqueue *vq)├─ virtqueue_get_buf()          // 获取完成描述符├─ dma_unmap_single()           // 解除DMA映射└─ dev_consume_skb_any()        // 释放sk_buff

四、数据接收流程(RX)

1. 核心流程
Network StackVirtio DriverVirtio BackendPhysical NIC应用接收网络数据从RX virtqueue获取缓冲区DMA写入数据更新used ring发送中断通知调度NAPIvirtnet_poll()从used ring取描述符构造sk_buffnapi_gro_receive()补充新缓冲区virtqueue_kick()传递数据Network StackVirtio DriverVirtio BackendPhysical NIC应用
2. 关键函数
// 中断处理
virtnet_interrupt()└─ napi_schedule()             // 调度NAPI轮询// 接收处理
virtnet_poll(struct napi_struct *napi)├─ virtqueue_get_buf()         // 获取接收描述符├─ virtnet_receive_skb()       // 构造sk_buff├─ napi_gro_receive()          // 提交协议栈└─ virtqueue_add_inbuf()       // 补充新缓冲区

五、关键数据结构

1. virtio_device
struct virtio_device {struct device dev;             // 设备模型struct virtio_device_id id;    // 设备标识struct virtio_config_ops *config; // 配置操作struct list_head vqs;          // virtqueue列表u64 features;                  // 协商特性void *priv;                    // 驱动私有数据
};
2. virtqueue
struct virtqueue {struct list_head list;         // 设备链表void (*callback)(struct virtqueue *vq); // 回调函数const char *name;              // 队列名称struct virtio_device *vdev;    // 关联设备unsigned int index;            // 队列索引void *priv;                    // 私有数据struct vring vring;            // 虚拟环结构
};
3. vring (核心通信结构)
struct vring {unsigned int num;              // 描述符数量struct vring_desc *desc;       // 描述符表struct vring_avail *avail;     // 可用环struct vring_used *used;       // 已用环
};
4. virtnet_info (网络设备私有数据)
struct virtnet_info {struct virtio_device *vdev;     // virtio设备struct net_device *dev;         // 网络设备struct virtqueue *rvq, *svq;    // 接收/发送队列struct receive_queue *rq;       // 接收队列数组struct send_queue *sq;          // 发送队列数组u16 curr_queue_pairs;           // 活动队列对struct bpf_prog __rcu *xdp_prog; // XDP程序
};

六、性能优化机制

1. 批处理优化
高开销
减少通知次数
VRING_AVAIL_F_NO_INTERRUPT
单包处理
性能瓶颈
批量处理
吞吐量提升
延迟通知
降低中断频率
2. NAPI机制
// 混合中断与轮询
static int virtnet_poll(struct napi_struct *napi, int budget)
{while (packets < budget && (buf = virtqueue_get_buf(vq, &len))) {// 处理数据包packets++;}if (packets < budget) {napi_complete(napi);       // 退出轮询模式virtqueue_enable_cb(vq);    // 启用回调}return packets;
}
3. 零拷贝技术
接收零拷贝
发送零拷贝
数据拷贝
DMA直接访问
mmap
直接访问
固定映射
直接写入
驱动DMA区域
预注册内存
用户空间
驱动DMA区域
用户空间内存
物理网卡
传统方式
高CPU开销
零拷贝
CPU效率提升

七、错误处理机制

1. 队列满处理
netdev_tx_t start_xmit(...)
{if (virtqueue_full(vq)) {netif_stop_queue(dev);    // 停止协议栈入队return NETDEV_TX_BUSY;    // 通知重试}// ...正常发送...
}// 在完成中断中恢复
void skb_xmit_done(...)
{if (netif_queue_stopped(dev) && !virtqueue_full(vq)) {netif_wake_queue(dev);    // 唤醒协议栈}
}
2. 设备重置恢复
static void virtnet_reset(struct virtio_device *vdev)
{// 1. 停止所有数据传输virtnet_freeze_down(vdev);// 2. 重置设备状态virtio_reset_device(vdev);// 3. 重新协商特性virtio_negotiate_features(vdev);// 4. 重建virtqueuesvirtnet_del_vqs(vi);virtnet_find_vqs(vi);// 5. 恢复数据传输virtnet_restore_up(vdev);
}

八、多队列支持

1. 配置流程
支持
检查VIRTIO_NET_F_MQ
读取max_queue_pairs
配置实际队列数
分配队列资源
设置CPU亲和性
启用RSS/Flow Director
2. 数据分发
// 发送队列选择
u16 virtnet_select_queue(struct net_device *dev, struct sk_buff *skb)
{// 1. XDP优先if (vi->xdp_prog)return vi->curr_queue_pairs;// 2. 使用RSS哈希return skb_get_hash(skb) % vi->curr_queue_pairs;
}// 接收中断绑定
static irqreturn_t virtnet_interrupt(int irq, void *dev_id)
{struct receive_queue *rq = dev_id;napi_schedule(&rq->napi);  // 调度对应队列的NAPI
}

九、XDP支持

1. 工作流程
XDP_PASS
XDP_TX
XDP_REDIRECT
XDP_DROP
网络数据
驱动RX路径
XDP程序
协议栈
原路返回
其他设备/CPU
丢弃数据包
2. 关键实现
static struct sk_buff *virtnet_run_xdp(...)
{struct bpf_prog *xdp_prog = rcu_dereference(rq->xdp_prog);xdp_prepare_buff(xdp, buf, offset, len);act = bpf_prog_run_xdp(xdp_prog, xdp);switch (act) {case XDP_PASS:return build_skb(...);case XDP_TX:xdpf = convert_to_xdp_frame(xdp);virtnet_xdp_xmit(dev, 1, &xdpf, 0);break;case XDP_REDIRECT:xdp_do_redirect(dev, xdp, xdp_prog);break;}
}

十、总结:Virtio核心优势

  1. 标准化接口

    • 统一的前后端通信协议
    • 支持多种传输机制(PCI、MMIO、channel)
  2. 高性能设计

    • 零拷贝数据传输
    • 批处理与延迟通知
    • 多队列并行处理
  3. 灵活扩展性

    • 特性协商机制
    • 可扩展的virtqueue设计
    • 支持现代功能(XDP、TLS offload)
  4. 跨平台支持

    • 支持KVM、QEMU、Docker等环境
    • 兼容多种客户机OS(Linux、Windows)
  5. 生产级可靠性

    • 完善的错误恢复机制
    • 热升级支持
    • 实时监控接口

Virtio通过将虚拟设备标准化,在保持高性能的同时,显著降低了虚拟化环境中I/O栈的复杂度,成为现代云计算基础设施的核心组件。其设计思想也影响了物理设备驱动的发展,推动了零拷贝、多队列等技术在物理网卡中的广泛应用。

http://www.lryc.cn/news/616254.html

相关文章:

  • 太极行业观察:从传统技艺到数字化转型的演变|创客匠人
  • 【R studio数据分析】准备工作——下载安装
  • 【布局适配问题】响应式布局、移动端适配、大屏布局要点
  • 通过sealos工具在ubuntu 24.02上安装k8s集群
  • Loki+Alloy+Grafana构建轻量级的日志分析系统
  • FFmpeg实现音视频转码
  • Spring AOP 底层实现(面试重点难点)
  • AQS(AbstractQueuedSynchronizer)底层源码实现与设计思想
  • 前端路由:Hash 模式与 History 模式深度解析
  • Java Stream流详解:从基础语法到实战应用
  • Rust 实战四 | Traui2+Vue3+Rspack 开发桌面应用:通配符掩码计算器
  • 【算法题】:和为N的连续正数序列
  • 数学建模:控制预测类问题
  • Python 获取对象信息的所有方法
  • matlab实现随机森林算法
  • Doubletrouble靶机练习
  • 点击速度测试:一款放大操作差距的互动挑战游戏
  • #Datawhale AI夏令营#第三期全球AI攻防挑战赛(AIGC技术-图像方向)
  • 如何用分析方法解决工作中的问题?
  • 检索召回率优化探究五(BGE-M3 混合检索):基于LangChain0.3 集成Milvu2.5 向量数据库构建的智能问答系统
  • Linux系统编程Day11 -- 进程属性和常见进程
  • 学习模板元编程(3)enable_if
  • 【树状数组】Dynamic Range Sum Queries
  • [激光原理与应用-221]:设计 - 皮秒紫外激光器 - 常见技术难题、原因与解决方案
  • Linux-静态配置ip地址
  • 【无标题】命名管道(Named Pipe)是一种在操作系统中用于**进程间通信(IPC)** 的机制
  • 深度解析Linux设备树(DTS):设计原理、实现框架与实例分析
  • 基于Qt/QML 5.14和YOLOv8的工业异常检测Demo:冲压点智能识别
  • 线程池的核心线程数与最大线程数怎么设置
  • 基于FFmpeg的B站视频下载处理