dpdk技术详解_dpdk acl

本文深入剖析了DPDK中的igb_uio内核模块,详细介绍了如何通过UIO将网卡映射到用户态,包括uio模块分析、uio_info结构体实例化、igb_uio初始化过程、PCI内存资源映射以及中断处理机制。通过对/dev/uio文件的读写操作,实现了用户态对网卡中断的监听和响应。
摘要由CSDN通过智能技术生成

igb_uio 是 dpdk 内部实现的将网卡映射到用户态的内核模块,它是 uio 模块的一个实例。

igb_uio 是一种 pci 驱动,将网卡绑定到 igb_uio 隔离了网卡的内核驱动,同时 igb_uio 完成网卡中断内核态初始化并将中断信号映射到用户态。

igb_uio 与 uio 模块密切相关,我将从 uio 模块着手分析 igb_uio 模块的工作原理。

uio 模块分析

uio 是一种字符设备驱动,在此驱动中注册了单独的 file_operations 函数表,uio 设备可以看做是一种独立的设备类型。

file_operations 函数内容如下:

static const struct file_operations uio_fops = { 
   
	.owner		= THIS_MODULE,
	.open		= uio_open,
	.release	= uio_release,
	.read		= uio_read,
	.write		= uio_write,
	.mmap		= uio_mmap,
	.poll		= uio_poll,
	.fasync		= uio_fasync,
	.llseek		= noop_llseek,
};

复制

Jetbrains全家桶1年46,售后保障稳定 

该函树表在 uio_major_init 中初始化 cdev 结构体时使用,相关代码如下:

    cdev->owner = THIS_MODULE;
	cdev->ops = &uio_fops;
	kobject_set_name(&cdev->kobj, "%s", name);
	
	result = cdev_add(cdev, uio_dev, UIO_MAX_DEVICES);

复制

我们对 /dev/uioxx 文件的操作最终都会对应到对 uio_fops 的不同方法的调用上

uio_info 结构体及其实例化过程

uio 模块中的 idev 变量是一个指向 struct uio_device 的指针,struct uio_device 中又包含 一个指向 struct uio_info 的指针,struct uio_info 结构体内容如下:

struct uio_info { 

struct uio_device	*uio_dev;
const char		*name;
const char		*version;
struct uio_mem		mem[MAX_UIO_MAPS];
struct uio_port		port[MAX_UIO_PORT_REGIONS];
long			irq;
unsigned long		irq_flags;
void			*priv;
irqreturn_t (*handler)(int irq, struct uio_info *dev_info);
int (*mmap)(struct uio_info *info, struct vm_area_struct *vma);
int (*open)(struct uio_info *info, struct inode *inode);
int (*release)(struct uio_info *info, struct inode *inode);
int (*irqcontrol)(struct uio_info *info, s32 irq_on);
};

复制

每一个 uio 设备都会实例化一个 uio_info 结构体,uio 驱动自身不会实例化 uio_info 结构体,它只提供一个框架,可以在其它模块中调用 uio_register_device实例化 uio_info 结构体,在 dpdk 中,常见方式是在驱动绑定 igb_uio 的时候调用 uio_register_device 进行实例化。

igb_uio.c 中初始化当前设备 uio_info 结构过程

可以在 igb_uio.c 的 probe 函数 igbuio_pci_probe 中找到实例化的相关代码,摘录如下:

410     /* remap IO memory */
411     err = igbuio_setup_bars(dev, &udev->info);
.....................................................
428     /* fill uio infos */
429     udev->info.name = "igb_uio";
430     udev->info.version = "0.1";
431     udev->info.handler = igbuio_pci_irqhandler;
432     udev->info.irqcontrol = igbuio_pci_irqcontrol;
433 #ifdef CONFIG_XEN_DOM0
434     /* check if the driver run on Xen Dom0 */
435     if (xen_initial_domain())
436         udev->info.mmap = igbuio_dom0_pci_mmap;
437 #endif
438     udev->info.priv = udev;
...........................................................
478     /* register uio driver */
479     err = uio_register_device(&dev->dev, &udev->info);

复制

411 行调用 igbuio_setup_bars 映射 pci 设备 bar 中的内存区域,此函数代码如下:

332 static int
333 igbuio_setup_bars(struct pci_dev *dev, struct uio_info *info)
334 { 
   
335     int i, iom, iop, ret;
336     unsigned long flags;
337     static const char *bar_names[PCI_STD_RESOURCE_END + 1]  = { 

338         "BAR0",
339         "BAR1",
340         "BAR2",
341         "BAR3",
342         "BAR4",
343         "BAR5",
344     };
345     
346     iom = 0;
347     iop = 0;
348     
349     for (i = 0; i < ARRAY_SIZE(bar_names); i++) { 

350         if (pci_resource_len(dev, i) != 0 &&
351                 pci_resource_start(dev, i) != 0) { 

352             flags = pci_resource_flags(dev, i);
353             if (flags &
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值