`
totoxian
  • 浏览: 1071282 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多

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

分享到:
评论

相关推荐

    linux网卡驱动.doc

    这个文档可能会通过实际例子和步骤指导读者如何从头开始编写一个简单的网卡驱动,同时也可能涉及一些高级话题,如多队列、RSS(Receive Side Scaling)等性能优化技术。学习和理解这些内容对于想要在Linux环境下开发...

    嵌入式Linux内核及其驱动开发

    网络设备则涉及网络通信,例如网卡驱动。 在开发驱动程序时,开发者需要关注Linux内核的关键数据结构。这些数据结构记录了系统当前状态的信息,需要在物理内存中维护,并且只能由内核及其子系统访问。理解这些数据...

    LINUX的网卡驱动.rar

    Linux内核通常包含了对多种硬件的驱动,包括Realtek的这些网卡芯片。在大多数现代Linux发行版中,内核会自动识别并加载相应的驱动,使得这些网卡可以立即工作。但是,对于较旧或定制化的系统,可能需要手动安装或...

    Linux下网卡驱动程序源码分析.rar

    通过阅读源码,可以学习如何实现上述功能,理解Linux内核如何调度和管理网卡驱动。 9. **开发工具与调试**: 开发和调试网卡驱动时,通常会用到`insmod`/`rmmod`加载和卸载模块,`ethtool`进行硬件测试,以及`...

    linux下的rtl8139网卡驱动程序源代码.zip_linux 网卡驱动_rtl8139

    总之,通过分析和研究"linux下的rtl8139网卡驱动程序源代码",开发者可以增强对Linux驱动开发的理解,尤其是对于PCI设备和中断处理机制。这个过程不仅提升了技术水平,还有助于解决实际工作中遇到的硬件兼容性和性能...

    移植到linux2.6内核的cs8900网卡驱动

    总的来说,移植cs8900网卡驱动到Linux 2.6内核是一项涉及内核编程、设备驱动原理和嵌入式系统实践的工作。这个过程不仅需要深厚的Linux内核知识,还需要对目标硬件平台有深入的理解。通过这个过程,开发者不仅可以...

    Emulex be2net 网卡驱动 linux

    5. **队列管理**:驱动支持多队列技术,可以有效地分配网络I/O,提高并发处理能力,减少中断处理对系统的影响。 6. **节能特性**:支持节能模式,例如能根据网络活动动态调整设备的工作状态,降低能耗。 7. **冗余...

    Linux网络体系结构 Linux内核中网络协议的设计与实现

    在Linux内核中,驱动程序实现了对硬件设备的访问,如网卡驱动,它们负责将数据转化为可以在物理介质上传输的信号。 2. **数据链路层**:这一层负责数据帧的封装和解封装,如以太网协议(Ethernet)、PPP(点对点协议)...

    linux内核完全注释

    5. 设备驱动:Linux内核通过设备驱动程序与硬件交互,驱动程序是内核与硬件之间的桥梁,使得操作系统能控制和管理硬件设备,如键盘、鼠标、显示器、硬盘、网卡等。 在阅读《Linux内核完全注释》这本书时,读者会...

    深入理解 Linux 内核.pdf 高清下载

    - **网络设备驱动**:包括对以太网卡、无线网卡等各种网络设备的支持。 #### 5. **安全机制** - **权限与用户管理**:基于UNIX的安全模型,Linux内核提供了用户、组和权限的概念,确保了系统安全性。 - **安全...

    linux网络驱动开发文档

    3. **网络驱动接口**:Linux内核提供了一组统一的API,称为“网络驱动程序接口”(NDI),用于与网络设备交互。这些接口包括初始化、注册、注销、发送数据包、接收数据包等函数。 4. **网络驱动流程**:网络驱动的...

    国嵌嵌入式Linux内核驱动深入教班材配套2440(最新)

    1. **Linux内核结构**:介绍Linux内核的基本架构,包括进程管理、内存管理、文件系统、网络协议栈等核心模块,帮助读者建立起对整个内核运作的宏观认识。 2. **驱动程序模型**:讲解Linux内核中的驱动模型,如...

    Linux内核以及驱动程序设计

    《Linux内核以及驱动程序设计》这本书主要涵盖了Linux操作系统的核心机制和驱动程序的开发方法,尽管基于较旧的2.4版本内核,但其中的许多理论和实践知识仍然具有很高的参考价值。Linux内核是开源操作系统的基石,...

    Linux网卡驱动学习笔记

    本文档旨在深入探讨Linux操作系统中DM9000网卡驱动的工作原理和技术细节,通过对关键概念、结构体成员及其功能的详细解释,帮助读者更好地理解Linux网络子系统及DM9000网卡驱动的设计思想。 #### 二、Linux网络子...

    linux下网卡驱动

    以上内容只是Linux下网卡驱动的冰山一角,实际开发和优化过程中,还需要考虑性能调优、电源管理、多队列技术等因素。对于开发抓包程序的程序员,理解这些基础知识至关重要,有助于编写更高效、可靠的网络应用程序。...

    linux内核学习资料

    - Linux内核由多个子系统组成,包括进程管理、内存管理、文件系统支持、网络堆栈等。 #### 2. **内核编译与配置** - 使用`make menuconfig`或`make xconfig`等工具来配置内核选项。 - 配置过程中可以选择启用或...

    Intel e1000 网卡驱动(Linux)分析

    ### Intel e1000 网卡驱动(Linux)分析 #### 加载之前 在Intel e1000网卡驱动加载之前,首先要完成驱动的初始化工作。这部分主要是通过定义特定的PCI设备来实现的。 为了匹配特定的PCI设备,使用了`PCI_DEVICE`宏...

    国嵌培训课件Linux驱动程序设计

    第一天 1.Linux驱动简介 2.字符设备驱动程序设计 3.驱动调试技术 ...2. Linux网卡驱动程序设计 3. Dm9000网卡驱动程序分析 4. 触摸屏驱动程序设计 第六天 1. PCI驱动程序设计 2. 串口驱动程序设计

Global site tag (gtag.js) - Google Analytics