当前位置:七道奇文章资讯系统安全Linux安全
日期:2011-01-23 03:26:00  来源:本站整理

<b>Linux网络报文接纳与发送概述</b>[Linux安全]

赞助商链接



  本文“<b>Linux网络报文接纳与发送概述</b>[Linux安全]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:

关于linux内核来说,网络报文由网络设备来举行接纳.设备驱动程序从网络设备中读取报文,通过内核供应的网络接口函数,将报文传送到内核中的网络协议栈.报文经过协议栈的处理,或转发、或丢弃、或被传送给某个进程.

网络报文的发送与之相反,进程通过系统调用将数据送入网络协议栈,大概由网络协议栈自己发动报文的发送,然后协议栈通过调用网络接口函数来调度驱动程序,使其将报文传送给网络设备,从而发送出去.

本文谈论的是网络接口层,它是网络设备驱动程序与网络协议栈交互的纽带.见下图中红色部份的netif.

 

报文的接纳

网络报文的接纳源自网络设备.网络设备在接纳到一个报文之后,通过中止奉告CPU.网卡驱动程序需求注册对该中止事件的处理函数(拜见《linux中止处理浅析》),以处理接纳到的报文.

在中止处理函数中,网络驱动程序有两种办法对报文举行处理(老式的办法,和新式的办法),我们先介绍老式的处理方法.在这种方法下,中止处理函数主要完成以下工作:

分配一个skb构造(该构造用于保存一个报文).操作设备,将设备收到的数据拷贝到这个skb构造对应的缓冲区中.设置skb的协议范例skb->protocol,该范例表明了网络协议栈的上层协议(下面我们将会看到).然后调用内核供应的网络接口函数netif_rx;

netif_rx(skb);

netif_rx函数对skb的如时间戳这样的附加信息举行初始化今后,将这个skb构造放入当前CPU的softdate_net构造的input_pkt_queue行列中.netif_rx会按照行列的长度,对设备的堵塞情况举行判断(行列太长则代表报文接纳过快,乃至于上层来不及处理).假如设备已陷入堵塞,则收到的报文大概直接被丢弃.

假如一切正常,netif_rx会调用网络接口函数netif_rx_schedule,以触发对接纳报文的进一步处理;

netif_rx_schedule(dev);

netif_rx利用softdate_net构造中内嵌的backlog_dev作为dev来调用netif_rx_schedule,后者将其加入到softdate_net构造的poll_list行列中(假如这个dev不在行列中的话),以使其等候被调度.

相比老式的处理方法,新式的处理方法(称为NAPI)在中止处理函数中仅仅是以对应设备的dev构造为参数调用netif_rx_schedule函数便可.

最后netif_rx_schedule函数会触发NET_RX_SOFTIRQ软中止,于是接下来对应的软中止处理函数net_rx_action将被调用;

net_rx_action();

关于当前CPU对应的softdate_net构造的poll_list行列中的全部dev,调用dev->poll办法.该办法是由对应dev的驱动程序实现的,用于接纳及处理报文(前面提到的backlog_dev除外).

net_rx_action每次运行都有一定的限度,并不一定要将全部报文都处理完.在处理完一定数目的报文配额、或处理历程超越一按时间后,net_rx_action便会返回.返回前触发一次NET_RX_SOFTIRQ软中止,等候下一次中止到来的时刻持续被调度.

以上历程如图所示(摘自ULNI):

 

上面提到的softdate_net构造是用于举行报文收发调度的构造,内核为每个CPU保护一个这样的构造.在报文接纳历程顶用到了此中的三个成员:

1、poll_list,网络设备dev的行列.此中的设备接纳到了报文,需求被处理;

2、input_pkt_queue,skb报文构造的行列,保存了已接纳并需求被处理的报文;

3、backlog_dev,一个虚拟的网络设备dev构造;

后两个成员是专门为支持老式的处理方法而设置的,在这种方法下,接纳到的skb被放入input_pkt_queue行列,然后backlog_dev被加入poll_list.而最后,自然backlog_dev->poll函数将对input_pkt_queue行列中的skb举行处理.backlog_dev->poll等于process_backlog函数;

process_backlog(backlog_dev, budget);

既然net_rx_action每次运行都有一个配额,它在调用dev->poll时也会传送当前剩余的配额值,即budget.

process_backlog会遍历input_pkt_queue行列中的skb,调用netif_receive_skb函数对其举行处理.

process_backlog函数有两种终局,一个是配额到或时间到,直接返回;另一个是处理完input_pkt_queue行列中的全部skb,此时需求将backlog_dev从poll_list中删除.

新式的NAPI处理方法所要做的事跟老的处理方法其实是很近似的.在其对应的dev->poll函数中,需求分配skb构造、从设备读取报文、调用netif_receive_skb让网络协议栈的上层来处理报文.

 

这种方法最大的好处是:在dev->poll函数中,不一定只处理一个报文.具体怎么处理可以由驱动程序机动掌握.比方说,假定目前网络负载非常大,假如网络设备每接纳一个报文都通过一次中止来奉告内核,这样做效率并不睬想.而此时dev->poll可以做一些轮询的工作,假如网络设备已经接纳了多个报文,可以一次性都处理了.并且,就算设备目前所接纳到的报文都已经处理完了,驱动程序也可以按照某种方法预判设备在很短的一段时间内还将收到报文,于是仍然将自己对应的dev构造留在poll_list中,等候下一次持续被调度.

当dev仍构造留在poll_list中时,设备驱动程序可以关闭设备接纳到报文时的中止告诉,因为目前处于轮询状况.而当驱动程序认为在将来的一段时间以内无报文可收时,则可以将其dev从poll_list中移除,然后开启设备接纳到报文时的中止告诉.等候下一次报文接纳的中止到来时,这个dev再重新被放入poll_list.

netif_receive_skb(skb);

该函数会将skb提交给抓包程序举行处理、还会触发数据链路层的桥接功效(见《linux网桥浅析》)、然后将报文提交给网络协议栈的上层(网络层)举行处理.

网络层的协议有IP、ARP等等很多种,在这里怎么知道这个skb该提交给哪类协议呢?在报文的数据链路层报头中保存着三个重要信息,发送者和接纳者的Mac地址、和上层协议标识.回想一下之前的流程,在skb接纳完成之后我们就已经设置了skb->protocol(从报头中得到),上层协议就由它来指定.比方,0x0800代表IP协议、0x0806代表ARP协议,这是由协议规定的.

netif_receive_skb并非用一个switch-case来匹配skb->protocol,以挑选网络层处理函数的.系统中有一个名为ptype_base的hash表,各种网络层的协议在其初始化时城市在这个hash表中注册一个范例为packet_type的表项(以协议范例为key),以下图所示(摘自ULNI):

 

netif_receive_skb要做的就是在这个hash表中遍历全部type与skb->protocol匹配的packet_type构造(packet_type构造的dev可用于限定skb->dev,NULL表示不限),然后调用其func回调函数.(可见,一个报文有大概被多种协议所处理.)

至此报文被提交到了网络层,在这里就不持续深化了.

报文的发送

报文的发送是由网络协议栈的上层发动的.网络协议栈上层构造一个需求发送的skb构造后(该skb已经包含了数据链路层的报头),调用dev_queue_xmit函数举行发送;

dev_queue_xmit(skb);

该函数先会处理一些缓冲区重组、计算校验和之类的杂事,然后开始处理报文的发送.

发送报文有两种战略,有行列或无行列.这是由网络设备驱动程序在定义其对应的dev构造时指定的,普通的设备城市利用行列.

dev->qdisc指向一个行列的实例,里面包含了行列本身以及操作行列的办法(enqueue、dequeue、requeue).这些办法的调集构成了一种行列法则(skb将以某种法则入队、以某种法则出队,并不一定是简单的先进先出),这样的法则可用于流量掌握.

网络设备驱动程序可以挑选自己的设备利用什么样的行列,或是不利用行列.

关于有行列的设备,dev_queue_xmit调用dev->qdisc->enqueue办法将skb加入行列,然后调用qdisc_run函数.而qdisc_run会调用qdisc_restart来对行摆列行处理.

qdisc_restart(dev);

该函数主要的工作就是不断调用dev->qdisc->dequeue办法从行列中取出待发送的报文,然后调用dev->hard_start_xmit办法举行发送.该办法是由设备驱动程序实现的,会直接和网络设备去打交道,将报文发送出去.

假如报文发送失利,qdisc_restart会调用dev->qdisc->requeue办法将skb重新放回行列.同时,还将调用netif_schedule函数将dev加入softdate_net的output_queue行列中(此中的设备都是有报文等候发送的,将在稍后被处理).然后触发一次NET_TX_SOFTIRQ软中止.于是在下一此中止到来时,对应的软中止处理函数net_tx_action将被调用.

而假如dev->hard_start_xmit办法发送报文成功,则表示报文已经送到了网络设备的发送缓冲区,设备会自动将报文发送出去.并且在报文发送完成时,设备会通过中止告诉驱动程序.对应的中止处理函数也会触发NET_TX_SOFTIRQ软中止.此外,已发送完成的skb将被加入softdate_net的completion_queue行列中,等候被释放.

软中止NET_TX_SOFTIRQ被触发,将使得net_tx_action函数被调用.该函数主要做了两件事:

1、从softdate_net的completion_queue行列中取出每一个skb,将其释放;

2、关于softdate_net的output_queue行列中的dev,调用qdisc_run持续尝试发送其qdisc行列中的报文;

关于有行列的设备,其行列主要用于流量掌握以及发送失利时的缓冲;关于没有行列的设备(比方lo,环回设备),dev_queue_xmit函数则会直接调用dev->hard_start_xmit举行发送,假如失利报文就会被丢弃.

以上历程如图所示:

 

qdisc_restart函数在履行历程中还会关心dev能否被暂停(就如接纳报文时要关心网络能否堵塞一样),假如被暂停则完毕处理流程并返回.

而dev的暂停与否是由设备驱动程序来设置的,在dev->hard_start_xmit函数中,驱动程序假如发现设备当前的发送缓冲区太小(比方小到无法再包容一个报文.这表示报文发送过快,乃至于设备来不及处理),则会让设备暂停.而当网络设备在完成报文的发送后会产生中止,对应的中止处理程序又可以按照设备当前的发送缓冲区大小,决意能否让设备从暂停中恢复.

而假如网络设备呈现问题,无法发送报文了,则大概设备上的发送缓冲区一向处于被占满的状况,招致设备一向被暂停.另一方面,报文发不出去,也就不会有告诉发送完成的中止产生,设备也就不会从暂停状况恢复,于是网络就瘫痪了.

为了检测这种情形,驱动程序可认为设备设置一个看门狗按时器.假如发现设备正在暂停状况,并且距离最后一次发送报文已经过去一定的时间,而发送完成的中止还没有收到,则认为该设备呈现问题.此时看门狗按时器将触发驱动程序供应的相关函数,将设备复位,以试图让其恢复正常工作.   以上是“<b>Linux网络报文接纳与发送概述</b>[Linux安全]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:

  • <b>hosts是什么 hosts文件在什么位置 若何改正hosts</b>
  • <b>在 Windows 8 中手动安装语言包</b>
  • <b>五个常见 PHP数据库问题</b>
  • Windows中Alt键的12个高效快速的利用本领介绍
  • <b>MySQL ORDER BY 的实现解析</b>
  • <b>详解MySQL存储历程参数有三种范例(in、out、inout)</b>
  • <b>Win8系统恢复出来经典的开始菜单的办法</b>
  • <b>Win8系统花屏怎么办 Win8系统花屏的办理办法</b>
  • <b>Windows 7系统下无线网卡安装</b>
  • <b>为什么 Linux不需求碎片整理</b>
  • <b>Windows 8中删除账户的几种办法(图)</b>
  • <b>教你如安在win7下配置路由器</b>
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .