linux内核对网卡驱动多队列的支持

linux的招牌就是它强大的网络功能,稳定,高效,能随着现实的日新月异而日趋完善。众所周知,linux的网卡由结构体net_device表示,一 个该结构体对应一个可以调度的数据包发送队列,注意,这里不谈数据包接收,数据包的实体在内核中以结构体sk_buff表示,这样的话,上述文字就可以用 以下图示来表示:

所谓的网卡对发送数据包的调度指的是多个数据包共享一个网卡的规则,当然就要拥有一系列的约定,比如区分数据包的优先级,区分数据包的类型,内核根据不同的调度策略来对不同的数据包进行排队,然后按照队列的顺序进行发送,关于这些细节不是本文要讨论的内容,可以参考linux内核对网络流量控制的支持方面的资料,需要明白的是,以往不支持多队列的内核中每个网卡拥有一个排队规则,然后根据排队规则的过滤器将数据包区分为一个一个的类,类中还可以嵌套新的更 细的排队规则,这个过程可以看到是以网卡为中心的,因为是每网卡一队列,这个队列指的是根队列,以网卡为中心实际上是一种过时的方式,还可以看成是以现在的观点来看偷懒的方式,毕竟网卡是内核和整个系统中的静态数据,是完全可以把握的,可是这已经不能适合当今的网络应用了,当今是一个必须适应大环境的世界 而不再是局部意义上的入乡随俗的世界了,丰富的数据没有必要入linux网卡的乡随网卡唯一的根队列的俗了,取而代之的是必须为丰富的网络数据提供属于它 们自己的舞台而不是逼迫它们强挤到网卡的根队列等待调度。我们来看一下具体的意义。
特别在无线设备上,几乎都是网络应用,有声音,有视频,有电子邮件,有实时数据等等。如果将这些数据都统一到一个队列中当然是可以的,因为2.6.27之 前的内核并没有因为没有实现多队列而出现问题,但是这么做是有弊端的,因为我们将必须用一种统一的方式管理它们,可实际上它们的区别很大很大,如果统一的队列有一些什么限制的话,这种限制将会限制到所有的数据,这将导致调度程序的复杂化。事实上真的需要将事情搅和在一起从而必须增加复杂性吗?我们在遇到困 难的时候必须想想现实是什么样子的,然后我们按照真实的世界的样子去做就会得到最好的解决方案,返璞归真真的是一条亘古不变的真理。实现了多队列,每个网卡将拥有很多的根队列,每个应用一个都有可能,这样的话我们就可以随心所欲的控制并且仅仅控制我们想控制的数据包了,比如视频数据强调实时性而对数据的准 确性要求不高,这样我们需要给视频数据包队列更高的发送优先级,为了不使视频效果变得很卡,我们缩短视频数据包队列的长度,而对那些要求准确性但是不要求实时的比如电子邮件的数据包队列,我们可以降低其优先级但是增加队列的长度,仅此而已,不需要变更已经很优美的调度机制就可以轻松实现。实现了多队列的网 卡的图示如下:

前面简要说明了多队列的意义,在对内核的更改上也很简单,就是将原先的每个net_device一个的队列改为多个就可以了:
static inline void qdisc_reset_all_tx(struct net_device *dev)
{
-       qdisc_reset(dev->tx_queue.qdisc);
+       unsigned int i;
+       for (i = 0; i < dev->num_tx_queues; i++)
+               qdisc_reset(netdev_get_tx_queue(dev, i)->qdisc);
}
int dev_queue_xmit(struct sk_buff *skb)
{
        struct net_device *dev = skb->dev;
@@ -1702,7 +1708,7 @@ int dev_queue_xmit(struct sk_buff *skb)
        }
gso:
-       txq = &dev->tx_queue;
+       txq = dev_pick_tx(dev, skb);
        spin_lock_prefetch(&txq->lock);
        /* Disable soft irqs for various locks below. Also
@@ -3788,8 +3794,9 @@ static void rollback_registered(struct net_device *dev)
        dev_put(dev);
}
dev_pick_tx之后的一些代码就是:

...

txq = dev_pick_tx(dev, skb);  //选出一个队列,不像以前那样的直接得到本网卡的队列。

q = rcu_dereference(txq->qdisc);

if (q->enqueue) {  //这之后的q就和没有多队列支持的q是一样的了。

spinlock_t *root_lock = qdisc_lock(q);

spin_lock(root_lock);

if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) {

kfree_skb(skb);

rc = NET_XMIT_DROP;

} else {

rc = qdisc_enqueue_root(skb, q);

qdisc_run(q);   //这应该很熟悉了

}

spin_unlock(root_lock);

goto out;

}

...

我们看一下dev_pick_tx:

static struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb)

{

u16 queue_index = 0;

if (dev->select_queue)

queue_index = dev->select_queue(dev, skb); //选择一个索引,这个策略可以设置,比如优先选择视频和音频队列,而哪个队列邦定哪个策略也是设定的。

else if (dev->real_num_tx_queues > 1)

queue_index = simple_tx_hash(dev, skb);

skb_set_queue_mapping(skb, queue_index);

return netdev_get_tx_queue(dev, queue_index);

}

另外,在网卡的hard_start_xmit中,驱动程序可以反馈给调度代码是否继续调度该队列或者下一个调度哪个队列,这些的具体策略全看场景怎么设置了,linux总是可以在机制和策略之间达到一个完美的平衡,比如利用一些标志位之类的小技巧。

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

原文地址:https://www.cnblogs.com/ksiwnhiwhs/p/10389127.html

时间: 2024-08-28 21:04:22

linux内核对网卡驱动多队列的支持的相关文章

【转】 linux内核移植和驱动添加(三)

原文网址:http://blog.chinaunix.net/uid-29589379-id-4708909.html 原文地址:linux内核移植和驱动添加(三) 作者:genehang 四,LED驱动的添加 1, 将led.c驱动文件拷贝到linux-3.1.4/drivers/char/目录下 [email protected]# pwd /change/linux-3.1.4/drivers/char [email protected]#  cp /mnt/hgfs/fh/driver/

Linux内核调用I2C驱动_以MPU6050为例

Linux内核调用I2C驱动_以MPU6050为例 0. 导语 最近一段时间都在恶补数据结构和C++,加上导师的事情比较多,Linux内核驱动的学习进程总是被阻碍.不过,十一假期终于没有人打扰,有这个奢侈的大块时间,可以一个人安安静静的在教研室看看Linux内核驱动的东西.按照Linux嵌入式学习的进程,SPI驱动搞完了之后就进入到I2C驱动的学习当中,十一还算是比较顺利,I2C的Linux驱动完成了. 为了测试I2C是否好用,选择一个常用的I2C传感器,手头有个MPU6050,刚好作为I2C的

决Ubuntu使用`make menuconfig`配置Linux 内核时,出现缺少&#39;ncurses-devel&#39;库支持。

*** Unable to find the ncurses libraries or the *** required header files. *** 'make menuconfig' requires the ncurses libraries. *** *** Install ncurses (ncurses-devel) and try again. ***  1. 问题状况 一般情况下使用系统自带的软件管理器apt-get就可以安装了(`sudo apt-get install 

s3c2440 移植linux内核 添加网卡支持 yaffs2文件系统支持

三.内核的移植 说明:针对的是百问网的jz2440 gcc:4.9.1 1.移植内核 首先,下载源码包:https://www.kernel.org/ 现在时间为2014年12月20日其主界面截图为: 在此,就在下较新的稳定的版本作为尝试.在这里有个命名问题需要说明一下,最前面的2.6或者3.18是主版本号码,后面的次版本号是比如2.6.32.65中的32,再后面的比如2.6.32.65中的65是升级版本号,主版本号为奇数的是开发本比如3.17,主版本号为偶数的为稳定版比如3.18,一般情况下名

基于tiny4412的Linux内核移植 -- MMA7660驱动移植(九-2)

作者信息 作者: 彭东林 邮箱:[email protected] QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本:Linux-4.4.0 (支持device tree) u-boot版本:友善之臂自带的 U-Boot 2010.12 (为支持uImage启动,做了少许改动) busybox版本:busybox 1.25 交叉编译工具链: arm-none-linux-gnueabi-gcc (gcc version 4

基于tiny4412的Linux内核移植 -- MMA7660驱动移植(九)

作者信息 作者: 彭东林 邮箱:[email protected] QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本:Linux-4.4.0 (支持device tree) u-boot版本:友善之臂自带的 U-Boot 2010.12 (为支持uImage启动,做了少许改动) busybox版本:busybox 1.25 交叉编译工具链: arm-none-linux-gnueabi-gcc (gcc version 4

linux下安装网卡驱动

1)网卡驱动不适配可能导致linux服务器网络时断时续 2)去官网下载驱动,检测到本机网卡类型为Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet,检测方法参考http://my.oschina.net/u/555061/blog/487239 3)到官网下载驱动,一般下载下来就是10k左右 4)查看Read Me文件 <Quick install with proper kernel settin

解决安装Linux之后没有网卡驱动

新买的一台HP台式机(HP EliteDesk 800 G2 TWR)安装Linux当做测试环境使用,安装完成之后发现没有网卡. 操作系统:Red Hat Enterprise Linux Server release 6.6 (Santiago) lspci查看有网卡的信息如下所示 [[email protected] ~]# lspci | grep 'Ethernet controller' 00:1f.6 Ethernet controller: Intel Corporation Et

linux内核交互,设备驱动控制管理接口

1,ioctl preface--starting point ,format,mount volume,in addition to the above file system -- allows users to store and retrive data; organized in a hierarchical directory tree,behaviorial semantics as spelled ou; ASM   shared disk cluster file system