Linux 网络堆栈的排队机制

网络性能篇 其实遇到很多问题的时候多看看内核日志就知道了,linux很智能的,很多报错信息都在日志里面,越遇到系统优化层面,就多要看看内核日志,43 | 套路篇:网络性能优化的几个思路(上) 阅读详情

转自:http://blog.jobbole.com/62917/

在任何网络堆栈或设备中,数据包的队列都是非常重要。这些队列使得不在同一时刻加载的模块能够相互通信,并且能提高网络性能,同时也会间接影响到网络延时的长短。本文章通过阐述IP数据包在Linux网络中的排队机制,来解释两个问题:

  • BQL一类新特性是如何减小网络延时的。
  • 如何控制已减小延时后的缓存。

下面这张图(和它的变形)将会在文中不断的出现,用以说明具体的概念。

figure_1_v2
figure1

驱动队列(环形缓存区)

驱动队列位于IP数据栈和网卡之间。驱动队列使用先进先出算法,并通过环形缓存区实现—可以暂时把环形缓存区当做一个固定大小的缓存器。这个队列中不含任何来自包(分组)的数据,直接参与排队的是描述符(descriptor)。这些描述符指向 “内核套接字缓存”(socket kernel buffers,简写为SKBs),SKB中含有在整个内核处理过程中都要使用的数据包。

figure_2_v2
figure2

进入驱动队列的数据,来自IP数据栈,在IP数据栈里所有的IP数据包都要进行排队。这些数据包可以从本地获得,当某个网卡在网络中充当路由器时,数据包也可以从网卡上接收,找到路由后再发出去。从IP数据栈中进入驱动队列的数据包,先由硬件使之出列,再通过数据总线发送到网卡上,以进行传输。

驱动队列的用处在于,只要系统有数据需要传输时,数据能够马上被传送到网卡进行及时传输。大致意思就是,驱动队列给了IP数据栈一个排队的地方,通过硬件来对数据进行不同时的排队。实现这个功能的另一种做法是,只要当物理传输媒介准备好传输数据时,网卡便马上向IP数据栈申请数据。但是因为对IP数据栈的数据申请,不可能马上得到相应,所以这种办法会浪费掉大量宝贵的传输资源,使吞吐量相应地降低。还有另一种正好相反的办法—在IP数据栈准备好要传输的数据包后,进行等待,直到物理传输媒介做好传输数据的准备为止。但是这种做法同样也不理想,因为在等待时IP数据栈被闲置,没有办法做别的工作。

栈中的超大数据包

多数网卡都有最大传输单位(MTU),用来表示能够被物理媒介传输的最大帧数。以太网的默认MTU为1500字节,也有一些支持Jumbo Frames的以太网MTU能够达到9000多字节的。在IP数据栈中,MTU同时也是数据包传输的极限大小。比如,有个应用需要向TCP接口传送2000字节的数据,这时,IP数据栈就必须创建两个数据包来传送它,因为单个MTU小于2000字节。所以在进行较大数据的传输时,MTU如果相对较小,那么大量数据包就会被创建出来,并且它们都要在物理媒介上传输到驱动队列中。

为了避免因为MTU大小限制而出现的大量数据包,Linux内核对传输大小进行了多项优化:TCP段装卸(TCP segmentation offload,简称TSO),UDP碎片装卸(UDP fragmentation offload,简称UFO)和类型化段装卸(generic segmentation offload ,简称GSO)。这些优化办法,使得IP数据栈能够创建比MTU更大的数据包。对于IPv4来说,优化后能够创建出最大含65536的数据包,并且这些数据包和MTU大小的数据包一样能够进入驱动队列排队。在使用TSO和UFO优化时,由网卡将较大的数据包拆分成能够传输的小数据包。对于没有该硬件拆分功能的网卡,GSO优化能够通过软件来实现相同的功能,在数据包进入驱动队列前迅速完成数据包拆分。

我在前面提过,驱动队列中能包含描述符的数量是一定的(但描述符可以指向不同大小的数据包)。所以,TSO,UFO和GSO等优化措施将数据包增大,也不完全是件好事,因为这些优化也会使驱动队列中进行排队的字节数增大了许多。图像3是一个与图像2的对比图。

figure_3_v2
figure3

虽然接下来我要将重点放在传输路径(transmit path)上了,但是这里还是要再强调一下,Linux在数据接收端同样有类似TSO、UFO和GSO的优化措施。这些接收端优化措施同样也能将每个数据包的大小限制增大。具体来说,类型接收装卸(generic receive offload,简称GRO)使网卡能够将接收到的若干数据包合并成一个大数据包后,再传给IP数据栈。在传送数据包时,GRO能将原始数据包重组,使之符合IP数据包首尾连接的属性。GRO同样也会带来副作用:较大的数据包在传送时,可能会被拆分成了若干较小的数据包,这时,就会有多个数据包在同一数据流中同时进行排队。较大的数据包如果发生了这样的“微拆分”(micro burst),会对数据流之间的延时产生不利影响。

饿死和延时

虽然设置驱动队列—即在IP数据栈和硬件网卡间排队,非常便利,但这样做也带来“饿死和延时”的问题。

当网卡开始从驱动队列中取数据包时,如果恰好这时驱动队列为空队列,那么硬件其实就失去了一次传输数据的机会,也就将系统的吞吐量降低了。我们把这种情况叫做“饿死”(starvation)。需要注意的是,如果驱动队列为空,而此时系统又没有数据需要传输时,则不能称为“饿死”—-这是系统的正常情况。如何避免“饿死”是一个很复杂的问题,因为IP数据栈将数据包传入驱动队列的过程,和硬件网卡从驱动队列中取数据包的过程常常不是同时发生的。更加糟糕的是,这两个过程间的间隔时间很不确定,常常随着系统负载和网络接口物理介质等外部环境而变化。比如说,在一个非常繁忙的系统中,IP数据栈就很少有机会能把数据包加入到驱动队列缓存中,此时,很可能在驱动队列对更多数据包排队前,网卡就已经从驱动队列中取数据了。因此,如果驱动队列能变得更大的话,出现“饿死”的几率就会得到减小,并且系统吞吐量会相应提高。

虽然较大的队列能够保证高吞吐量,但是队列变大的同时,大量的延时情况也会出现。

figure_4_v2
figure4

在图像4中,单个带宽较大的TCP段几乎把驱动队列占满,我们把它称为“块(阻碍)交通流”(bulk traffic flow)(蓝色部分)。在最后进行排队的,是来自VoIP或游戏的“交互数据流”(黄色部分)。像VoIP或游戏一类的交互式应用,一般会在固定的时间间隔到达时,发送较小的数据包。这对延时是非常敏感的。并且这时,传输带宽较大的数据,会使包传送率(packet rate)增高而且会产生更大的数据包。较高的包传送率会很快占满队列缓存,进而阻碍交互性数据包的传输。为了进一步说明这种情况,我们先做出如下假设:

  • 网络接口的传输速率为 5Mbit/sec (5000000 bits/sec)。
  • 每个“块交通流”中的数据包(分组)大小为1500bytes(或12000bits)。
  • 每个“交互交通流”中的数据包(分组)大小为500bytes。
  • 驱动队列共能容纳128个描述符。
  • 现在有127个“块(阻碍)”数据包,和1个交互数据包最后进行排队。

127个数据传输完毕时,交互数据包才能进行传输。在以上假设下,将所有127个块数据包传输完毕共需要(127 * 12,000) / 5,000,000 = 0.304 秒 (以每ping计算延时则为304 毫秒 )。这样的延时完全无法满足交互式应用的需求,并且这个时间中还没有包含完成所有传输所需的时间—因为我们只计算了完成127个块数据包传输的时间而已。之前我曾提到过,在驱动队列中,数据包(分组)的大小在TSO等优化下能够超过1500bytes。所以这也让延时问题变得更严重了。

由超过规定大小的缓存而引起的较大延时,也被称为Bufferbloat。在Controlling Queue Delay 和the Bufferbloat中对这个问题有更详细的阐述。

综上所述,为驱动队列选择正确的大小是一个Goldilocks问题—不能定的太大因为会有延时,也不能定的太小因为吞吐量会降低。

字节队列限制(BQL)

字节队列限制(BQL)是最近在linux内核(> 3.3.0)中出现的新特性,它能为驱动队列自动分配合适的大小以解决前面提到过的问题。BQL机制在将数据包进行排队时,会自动计算当前系统下,能够避免饿死所需的最小驱动队列缓存大小,再决定是否对数据包进行排队。如前文所述,进行排队的数据越少,对数据包的最大延时也越小。

需要注意的是,驱动队列的实际大小并没有被BQL改变。BQL只是限制了当前时刻能够进行排队的数据多少(以字节计算)而已。任何超过大小限制的那一部分数据,都会被BQL阻挡在驱动队列之外。BQL机制会在以下两个事件发生时启动:

  1. 数据包进入驱动队列排队时。
  2. 通过物理介质的传输已经完成时。

下面是简化后的BQL算法。LIMIT指的是BQL计算出来的限制值。

1
2
3
4
5
6
****
** After adding packets to the queue
****
 
if the number of queued bytes is over the current LIMIT value then
         disable the queueing of more data to the driver queue

注意,进行排队的数据大小可以超过LIMIT,因为数据在进行LIMIT检查以前,就已经排队了。因为非常大的字节,能够通过TSO、UFO和GSO优化,一次性进行排队,所以就造成了进行排队数据过大的问题。如果你更加重视延时,也许你会将这些优化特性去除掉。文章后面有介绍去除的办法。

BQL机制的第二阶段,在硬件完成传输了以后启动。

1
2
3
4
5
6
7
8
9
10
11
12
13
****
** When the hardware has completed sending a batch of packets
** (Referred to as the end of an interval)
****
 
if the hardware was starved in the interval
         increase LIMIT
 
else if the hardware was busy during the entire interval (not starved) and there are bytes to transmit
         decrease LIMIT by the number of bytes not transmitted in the interval
 
if the number of queued bytes is less than LIMIT
         enable the queueing of more data to the buffer

如代码所示,BQL主要是在测试系统此时是否出现了饿死。如果出现了饿死,则LIMIT会增加,以使更多数据能够进去队列进行排队。如果系统在测试时间内一直都十分繁忙,而且仍有字节在等着传入队列中,则此时队列太大了,当前系统不需要这么大的队列,所以LIMIT会减小,以控制延时。

下面举一个实例,来帮助大家理解BQL是如何控制用于排队的数据大小的。在我的其中一个服务器上,默认的驱动队列大小是256个描述符。因为以太网MTU大小为1500bytes,所以此时驱动队列能对256 * 1,500 = 384,000 bytes进行排队(如果使用TSO、GSO则排队字节会更多)。但是,BQL此时计算出的LIMIT值为3012bytes。所以,BQL大大限制了能够进入队列的数据大小。

有关BQL非常有趣的一点,能够从B—byte 这个字母看出来。跟驱动队列的大小和其他数据包队列的大小单位不同,BQL以byte(字节)为单位进行操作。这是因为字节的数目,与其在物理介质上传输所需时间,有非常直接的关系。而数据包和描述符的数目与该时间则关系不大,因为数据包和描述符的大小都是不一样的。

BQL通过将排队数据的大小进行限制,使之保持在能避免饿死出现的最小值,来减少网络延时。BQL还有一个重要的特性,它能使原本在驱动队列中进行排队(使用FIFO算法排队)的数据包,转移到“排队准则”(queueing discipline (QDisc))上来进行排队。QDisc能够实现比FIFO复杂得多的排队算法策略。下一小节将重点介绍Linux的QDisc机制。

排队准则(QDisc)

我们已经了解到,驱动队列只是简单的先入先出队列,它不能将来自不同数据流的包区分开来。这样的设计能使网卡驱动软件变得小巧并且有更高的效率。需要注意的是,一些更加先进的以太网和无线网卡可以支持多种相互独立的传送队列,但是它们实际上都是非常类似的先进先出队列而已。系统中更高层负责在其中选择一种队列进行使用。

夹在IP数据栈和驱动队列中间的,是排队准则(QDisc)层(见Figure1),它负责实现Linux内核中的(数据传输)交通管理功能,比如交通分类,优先级别和速率协商。QDisc层的配置比起其他层要更加困难一些。要了解QDisc层,必须了解三个非常重要的概念:排队规则,类和过滤器。

排队准则(QDisc)是Linux对交通队列的抽象,但是比“先入先出”要复杂一些。通过网络接口,QDisc能独立地进行复杂的队列管理,而不需要改变IP数据栈或者网卡驱动的运行模式。每个网络接口都会默认被设为pfifo_fast QDisc ,pfifo_fast QDisc在TOS的基础上,实现了简单的三带优先机制(three band prioritization scheme)。虽然是默认机制,但是这并不代表它是最好的机制,因为pfifo_fast QDisc的队列深度很大(在下面txqueuelen中会有解释),并且它也不能区分不同数据流。

第二个和QDisc紧密相关的概念是类。单个QDisc能通过实现不同类,对数据中的不同部分进行不同处理。例如,层级表示桶(the Hierarchical Token Bucket (HTB))QDisc,能使用户配置500Kbps 和 300Kbps的类,并且控制数据使之进入用户希望其进入的类中。并不是所有QDisc都实现这种功能,我们一般把能够这样分类的QDisc称为——可分类的QDiscs。

过滤器(也叫分类器)是一种分类的机制,用来将数据分类到特定QDisc或类中。过滤器的种类很多,它们的复杂度也都不相同。u32 是其中最普通也最容易使用的一种。现在还没有针对u32的文档,但是你可以在这里找到一个例子one of my QoS scripts。

在LARTC HOWTO and the tc man pages,你可以了解到更多关于QDiscs、类和过滤器的细节。

传输层和排队准则间的缓存

你可能已经注意到了,在原来的图例中,排队准则层之上就没有数据包的队列了。这意味着网络数据栈要么直接把数据包放入排队准则中,要么把数据包推回它的上一层(比如套接字缓存的情况),如果这时队列已满的话。接下来一个很明显的问题是,当栈有很多数据包要发送的时候该怎么办?当TCP的拥塞窗口很大,或者某个应用正在快速发送UDP数据包时,就会出现要发送很多数据包的情况。对于只有一个队列的QDisc来说,类似问题在图例4中就已经出现过了。这里的问题是,一个带宽很大或者包速率很大的数据流会把队列里的所有空间占满,造成数据包丢失和延时的问题。更糟的是,这样很可能会使另一个缓存产生,进而产生一个静止队列(standing queue),造成更严重的延时并使TCP的RTT和拥塞窗口的计算出现问题。由于Linux默认使用仅有一个队列的pfifo_fast QDisc(因为大多数数据流的TOS=0),所以这样的问题非常常见。

Linux3.6.0(2012-09-30)出现后,Linux内核增加了TCP小队列(TCP small queue)的机制,用于解决该问题。TCP小队列对每个TCP数据流中,能够同时参与排队的字节数做出了限制。这样会产生意想不到的作用,能使内核将数据推回原先的应用,使得应用能更有效地优先处理写入套接字的请求。目前(2012-12-28),除TCP之外的其他传输协议的单个数据流,还是有可能阻塞QDsic层的。

另一种能部分解决传输层阻塞的办法,是使用有许多队列的QDsic层,最好是对每一个数据流都能有一个队列。SFQ和fq_codel的QDsic都能够很好地解决这个问题,使每个数据流都分到一个队列。

如何控制Linux中的队列长度

驱动队列

对于以太网设备,可以用ethtool命令来控制队列长度。ethtool提供底层的接口数据,并能控制IP数据栈和驱动的各种特性。

-g 能够将驱动队列的参数展示出来:

1
2
3
4
5
6
7
8
9
10
11
12
[root@alpha net-next]# ethtool -g eth0
Ring parameters for eth0:
Pre-set maximums:
RX:        16384
RX Mini:    0
RX Jumbo:    0
TX:        16384
Current hardware settings:
RX:        512
RX Mini:    0
RX Jumbo:    0
TX:        256

从上面可以看出,网卡驱动默认在传输队列中有256个描述符。前面我们提到过,为了免缓存丢包等情况,应该减小驱动队列的大小,这同时也能减小延时。引入BQL后,就没有必要再去调整驱动队列的大小了(下文中有配置BQL的介绍)。

ethtool也能用于调整优化特性,如TSO、UFO和GSO。-k 指令能展示出现在卸货(offload)状态,-K能调整这些状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[dan@alpha ~]$ ethtool -k eth0
Offload parameters for eth0:
rx-checksumming: off
tx-checksumming: off
scatter-gather: off
tcp-segmentation-offload: off
udp-fragmentation-offload: off
generic-segmentation-offload: off
generic-receive-offload: on
large-receive-offload: off
rx-vlan-offload: off
tx-vlan-offload: off
ntuple-filters: off
receive-hashing: off

因为TSO, GSO, UFO 和 GRO大大增加了能够参与排队的字节数,如果相比于吞吐量你更在意延时的话,你就应该禁用这些优化。一般来说禁用这些优化,不会使你感到CPU和吞吐量收到了影响,除非你的系统要处理的数据率很大。

字节队列限制(BQL)

BQL算法能够自我适应,所以应该没什么必要去经常调整它。但是,如果你很关注最大在低码率上的最大延时的话,可能你会想要比现有LIMIT更大的上限值。在/sys 的目录中可以找到配置BQL的文件,目录的具体地址取决于网卡的位置和名字。在我的服务器上,eth0的目录是:

1
/sys/devices/pci0000:00/0000:00:14.0/net/eth0/queues/tx-0/byte_queue_limits

里面的文件有:

  • hold_time:修改LIMIT间的时间(millisecond为单位)。
  • inflight:参与排队但没有发送的字节数。
  • limit:BQL计算出的LIMIT值。如果该网卡不支持BQL机制,则为0。
  • limit_max:能够修改的LIMIT最大值。调低该值能减小延时。
  • limit_min:能够修改的LIMIT最小值。调高该值能增大吞吐量。

为能够参与排队的字节数设置一个上限,改一下limit_max 文件就行了:

1
echo "3000" > limit_max

什么是txqueuelen?

在前面我们已经提到了减小网卡传输队列大小的作用。当前的队列大小能够通过ip和ifconfig命令获得。但是令人困惑地是,两个命令得到的队列长度不同:

1
2
3
4
5
6
7
8
9
10
[dan@alpha ~]$ ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:18:F3:51:44:10 
           inet addr:69.41.199.58  Bcast:69.41.199.63  Mask:255.255.255.248
           inet6 addr: fe80::218:f3ff:fe51:4410/64 Scope:Link
           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
           RX packets:435033 errors:0 dropped:0 overruns:0 frame:0
           TX packets:429919 errors:0 dropped:0 overruns:0 carrier:0
           collisions:0 txqueuelen:1000
           RX bytes:65651219 (62.6 MiB)  TX bytes:132143593 (126.0 MiB)
           Interrupt:23
1
2
3
4
5
[dan@alpha ~]$ ip link
1: lo:  mtu 16436 qdisc noqueue state UNKNOWN
     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
     link/ether 00:18:f3:51:44:10 brd ff:ff:ff:ff:ff:ff

默认的传输队列长度为1000包,在低带宽下这已经是很大的缓存了。

有趣的是,这个变量到底控制着什么东西呢?我以前也不知道,于是花了很多时间阅读内核代码。就我所知,txqueuelen只是丢某些排队准则的默认队列长度。这些排队准则有:

  • pfifo_fast (Linux default queueing discipline)
  • sch_fifo
  • sch_gred
  • sch_htb (only for the default queue)
  • sch_plug
  • sch_sfb
  • sch_teql

再来看图例1,txqueuelen参数控制着上面准则的队列大小。对于大多数其中的队列,tc命令行中的limit参数,都超过了txqueuelen的默认大小。总之,如果你不使用上面的队列准则,或者队列长度超过了exqueuelen大小,txqueuelen都是没有意义的。

再说一句,还有一点使我非常困惑,ifconfig命令显示的是如mac地址一类的底层网络接口细节,但是txqueuelen显示的却是更高层的QDisc层的信息。如果ifconfig显示驱动队列的大小可能会更合理些。

通过ip或者ifconfig命令能够控制传输队列的长度:

1
[root@alpha dan]# ip link set txqueuelen 500 dev eth0

注意,ip命令使用 ‘txqueuelen’,但在显示接口细节时使用的是‘qlen’。

队列准则

前面介绍过,Linux 内核有很多QDsic,每个QDisc有自己的包队列排队方法。在这篇文章里描述清楚如何配置这些QDisc的细节是不可能的。想要了解所有细节,可以参考man page(man tc)。在‘man tc qdisc-name’ (ex: ‘man tc htb’ or ‘man tc fq_codel’)中,能够找到每个QDisc的细节。LARTC也能找到许多有用的资源,但是缺少一些特性的资料。

下面是一些使用的tc命令的小技巧:

  • 如果数据包没有经过过滤器分类,HTBQDisc的默认队列会接收所有的数据包。其他QDisc比如DRR会把所有未分类的数据都接收进来。可以通过“tc qdisc show”中的direct_packets_stat查看到所有没有分类然后直接进入到队列中的数据包。
  • HTB类仅对没有带宽分配的分类起作用。所有带宽分配会在查看它们的叶子和相关的优先级时发生。
  • QDisc设施(infrastructure)会鉴别出带有大小数目(major and minor numbers )QDisc和类,它们被冒号分开。大数(major number)是QDisc的标识符,小数(minor number)标识QDisc中的类。tc命令使用十六进制来表示这些数字。因为很多字符串在十六和十进制中都一样(10以内),所以许多用户一直不知道tc使用十六进制表示法。可以在my tcscripts里看看我是如何对付它的。
  • 如果你使用的是ADSL,并且基于ATM(几乎所有DSL服务都是基于ATM的,但也有例外,比如基于VDSL2的),你很可能会想要加入“linklayer adsl”选项。它的意思是将IP数据包分解成53个字节大小的ATM块的上限。
  • 如果你正在使用PPPoE,那你很可能会想通过‘overhead’参数来调整PPPoE的上限。

TCP 小队列

每个套接字TCP队列的大小限制,可以通过下面的/proc文件来查看和控制:

1
/proc/sys/net/ipv4/tcp_limit_output_bytes

我觉得一般情况下都不需要修改这个文件。

你控制不了的超大队列

不幸的是,并不是所有影响网络性能超大队列都能够被我们控制。很常见的是,问题往往出在服务提供商提供的装置和其他配套的设备(比如DSL或者电缆调制器)上。当服务提供商的装置本身有问题时,就没什么办法了,因为你不可能控制向你传输的数据。但是,在逆向上,你可以控制数据流使之比链路率(link rate)稍微低些。这会让装置中的队列不会有几对数据包出现。很多家庭路由器都有链路率限制的功能,你能够通过它来控制你的数据流低于链路率。如果你将Linux Box作为路由器,控制数据流同时也会使内核的排队机制运行地更加高效。你能找到很多在线的tc脚本,比如the one I use with some related performance results。

概要

在每个使用分组交换的网络中,数据包缓存的排队机制都是非常必要的。控制这些缓存的包大小是至关重要的,能直接影响到网络延时等问题。虽然静态的缓存大小分配对于降低延时也很有效,但是更好的方法还是用更加智能的方法动态控制包的大小。实现动态控制的最好方法是使用动态机制,比如BQL和active queue management(AQM)技术,比如Codel。本文描述了数据包时如何在Linux的网络栈中进行排队的,并且介绍了相关特性的配置方法,给出了降低延时的建议。

相关链接

Controlling Queue Delay  – 对网络排队机制作和Codel算法出了很好的介绍,

Presentation of Codel at the IETF – Controlling Queue Delay 一文的视频版本

Bufferbloat: Dark Buffers in the Internet – 早先介绍数据流阻塞的文章

Linux Advanced Routing and Traffic Control Howto (LARTC)  – 可能是目前为止最好的tc命令使用文档,只是有些过时,没有包含fq_codel等特性。

TCP Small Queues on LWN

Byte Queue Limits on LWN

感谢

感谢Kevin Mason, Simon Barber, Lucas Fontes and Rami Rosen对文章所作出的帮助。

Linux TC 流量控制与排队规则 qdisc 树型结构详解(以HTB和RED为例) Linux 操作系统中的流量控制器 TC (Traffic Control) 用于Linux内核的流量控制,它规定建立处理数据包的队列,并定义队列中的数据包被发送的方式,从而实现对流量的控制。 阅读详情

相关推荐

linux网络知识和工具(持续更新)

涉及主机调优、网络性能调优、网络问题排查等方向,包含工具和原理的介绍了解ifconfig中的参数信息dropped与overruns的区别 dropped,表示这个数据包已经进入到网卡的接收缓存fifo队列,并且开始被系统中断处理准备进行数据包拷贝(从网卡缓存fifo队列拷贝到系统内存),但由于此时的系统原因(比如内存不够等)导致这个数据包被丢掉,即这个数据包被Linux系统丢掉。 overru

onephone的专栏 957

Linux网络的安全设置(基本命令)

这里写目录标题一. 查看网络设置1.1 查看网络接口1.2 查看主机名称1.3 查看路由条目1.4 查看网络连接情况1.5 获取socket统计信息二. 测试网络设置2.1 测试网络连接2.2 跟踪数据包2.3 域名解析三. 设置网络参数的方式3.1 设置网络接口的ip地址,子网掩码3.2 禁用或重启网卡3.3 设置虚拟网络接口3.4 设置路由记录route3.5 配置文件的路径 一. 查看网络设置 1.1 查看网络接口 ifconfig命令 查看所有活动的网络接口信息 ifconfig +网络

aaa1414124211的博客 529

介绍一种新的算法——Bootstrapped Double Q-Learning (BQL)算法,基于bootstrapping和intrinsic reward进行Q值更新

Q-learning算法是强化学习领域中非常经典的一类算法。它能够从离散或连续状态空间,用最优策略解决最优控制问题。其核心思想就是用收益函数(reward function)指导agent在每一个状态下做出动作的选择。但是,Q-learning存在着严重的不稳定性,即环境的变化会导致Q值的跳跃甚至完全崩溃,导致学习过程的困难。因此,如何保证Q值更新的稳定性是当今研究的一个重要课题。

AI天才研究院 1330

Linux 网络堆栈的排队机制(二)

排队准则(QDisc)我们已经了解到,驱动队列只是简单的先入先出队列,它不能将来自不同数据流的包区分开来。这样的设计能使网卡驱动软件变得小巧并且有更高的效率。需要注意的是,一些更加先进的以太网和无线网卡可以支持多种相互独立的传送队列,但是它们实际上都是非常类似的先进先出队列而已。系统中更高层负责在其中选择一种队列进行使用。夹在IP数据栈和驱动队列中间的,是排队准则(QDisc...

weixin_34342578的博客 644

CCS配置MSPM0G3507(七) 编码器(TIMER-QEI)

1.选择时钟源 BUSCLK2.时钟分频配置为1分频3.分频系数配置为14.若勾选 Start ,则生成程序后会自动开启定时器的计数,否则需手动在程序中开启5.Load Value 设置为65535。

kaneki_lh的博客 1万+

PPL文档——Excel制作的甘特图加上动态今日线

当很多项目需要跟踪进度时,我们介绍一种在Excel中创建甘特图。

qq_34777858的博客 7064

Linux 网络堆栈的排队机制(一)

在任何网络堆栈或设备中,数据包的队列都是非常重要。这些队列使得不在同一时刻加载的模块能够相互通信,并且能提高网络性能,同时也会间接影响到网络延时的长短。本文章通过阐述IP数据包在Linux网络中的排队机制,来解释两个问题:BQL一类新特性是如何减小网络延时的。如何控制已减小延时后的缓存。下面这张图(和它的变形)将会在文中不断的出现,用以说明具体的概念。figure1驱动队列(...

weixin_34203832的博客 458

第7篇-SAP MM模块-JIT应用实战解析,从计划协议到JIT供应的关键配置与流程

本文深入解析SAP MM模块中的JIT(Just In Time)供应模式,从计划协议到JIT供应的关键配置与流程。通过动态计划行管理、需求聚合与分解等核心功能,实现精确数量、时间和地点的物料供应。文章详细介绍了主数据准备、计划协议配置、MRP参数精调及EDI集成方案,并提供了实施中的典型问题与解决方案,助力企业优化供应链管理。

weixin_30363509的博客 948

Linux网络性能参数

介绍 有时,人们正在寻找能够带来高吞吐量和低延迟的sysctl 货物崇拜(cargo cult)值,而无需进行权衡,并且这种值在任何情况下都能工作。这是不现实的,尽管我们可以说新的内核版本在默认情况下已经进行了很好的调优。事实上,如果乱用默认值,可能会影响性能。 这个简短的教程展示了一些最常用和引用最多的sysctl/网络参数在Linux网络流中的位置,它深受Linux网络堆栈的插图指南和Marek Majkowski的许多帖子的启发。 请随意发送更正和建议!:) Linux网络队列概述 将sysct

sunny_98_98的博客 3481

No Target Connected 错误时的一种情况

STM32的SWD烧录模式No Target Connected 错误的一种情况 STM32的SWD烧录模式No Target Connected 错误时的一种处理情况 这是我第一次烧板子的时候遇到的问题,在给板子download的时候出现了“No Target Connected”的错误,这里讲一种解决方法。不一定适用于全部状况,但是可以作为一种纠错方法。 打开 Options for Target… 1.首先点击Options for Target…这个像魔棒一样的按键打开,会出现这个页面 2.点击

Logan_CodeGou的博客 1万+

Scratch离线版部署指南:解决资源缺失与页面显示异常问题

本文提供了一份详尽的Scratch离线版部署指南,旨在解决网络依赖导致的资源缺失与页面显示异常问题。通过从基础文件获取、自动化资源抓取到生产环境部署的完整流程,帮助教育工作者和开发者在无网络环境下搭建功能完整的本地Scratch编辑器,确保编程教学的顺利进行。

wine的专栏 1263

内核网络状态监控

查看相应参数在当前运行机器的值可以通过/proc/sys/net/目录下的文件内容查看。

wwwlyj123321的博客 558

车辆TBOX科普 第7次 TBOX技术深度解析:硬件架构与核心组件详解

摘要: TBOX(车载远程信息处理单元)是智能网联汽车的核心组件,承担数据采集、通信连接与安全交互等关键功能。其硬件架构以主控单元为核心,采用ARM架构处理器(如NXP i.MX系列)实现高效能低功耗处理,搭配DDR4/LPDDR5内存保障性能,eMMC/UFS存储确保数据可靠性。设计中需平衡车规级可靠性(AEC-Q100)、EMC兼容性及成本控制,同时集成通信、定位与安全模块。未来趋势聚焦异构计算、先进制程及功能安全(ASIL-D)与信息安全融合,推动TBOX向边缘计算节点演进。该技术是汽车智能化转型的重

IT深耕十余载,大道之简 862

FreeRTOS任务机制深度解析:状态、优先级、TCB与堆栈设计

嵌入式实时操作系统中,任务是资源调度与并发控制的核心抽象。其本质并非高级语言的线程封装,而是直接映射硬件上下文切换的确定性执行单元。理解任务状态机(就绪/阻塞/运行)、抢占式优先级调度原理,以及任务控制块(TCB)对寄存器现场的精确管理,是保障系统可预测性的基础。FreeRTOS任务以极小内存开销(典型128–512B堆栈)和微秒级响应能力,支撑工业控制、传感器节点等资源受限场景。本文聚焦任务创建、状态流转、堆栈计算与协程协同等硬核实践,结合TCB结构与eBlocked卡死排查,揭示裸机环境下多任务可靠运行

weixin_34216196的博客 292

下拉式菜单设计——Power BI

Power BI导航设计:多级下拉菜单

weixin_41542593的博客 5434

【CloudCompare教程】017:点云快速全局配准

点云数据的配准分为基于特征(特征点、特征线)的拼接和无特征拼接。特征点匹配的方法和全局ICP的方法。特征点的方法通过全局特征匹配达到全局配准,全局ICP的方法通过对变量空间进行搜索的方法达到全局最优解。

智慧空间实验室 3930

Linux - 网络子系统 - 网络设备子系统:TX

引用 链路层输出 - qdisc 多队列网卡简介以及Linux通过网卡发送数据包源码解读 Linux多队列网卡 Linux TCP队列相关参数的总结 Queueing in the Linux Network Stack Linux XPS实现 linux kernel 网络协议栈之xps特性详解 What is the mq qdisc in tc Traffic Control? Linux 高级流控 - IBM 网卡中断及多队列 ...

vertor11的博客 3546

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

详解 Linux 系统中断概念和处理过程

硬中断是由外部硬件设备触发的信号。它是设备向CPU发送的一种请求,以告知CPU该设备需要处理的事件或状态变化。硬中断通常由外部设备(如键盘、鼠标、网络接口卡、磁盘驱动器等)通过中断请求线(IRQ)向CPU发送信号。当设备完成数据传输、发生错误或状态变化时会产生硬中断。以下为硬中断的特点:异步: 硬中断是异步事件,不受当前正在执行的程序控制。快速响应: 硬中断通常会被立即处理,以确保及时响应设备的请求。优先级: 硬中断可以设置优先级,以便高优先级的中断可以中断低优先级的中断处理。软中断。

weixin_46919680的博客 1160

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Linux 存储栈的架构设计(一)

开源操作系统(如 Linux)的主要优势在于任何人都可以深入挖掘并揭示它们的内部工作原理。尽管软件开发领域取得了天文般的进步,但 Linux 内核仍然是最复杂的代码之一。开发者、程序员以及潜在的内核黑客们不断深入内核代码,并推动新功能的实现。像我这样的爱好者和技术爱好者也在尝试理解并解开其中的谜团。作为其中的一名爱好者,我花了相当多的时间探索 Linux 存储堆栈的复杂性。从简单的硬盘驱动器到复杂的网络存储系统,Linux 是世界上许多最复杂存储技术的核心。

龙哥盟 1413

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Linux网络管理工具tc

是用来管理和配置队列规则的命令。在 Linux 的网络堆栈中,每个网络接口都可以有自己的队列规则,这些规则决定了数据包如何在网络接口上排队、被处理和发送。通过不同的 qdisc 类型和参数,管理员可以精细地控制网络流量,例如限制带宽、控制延迟、优先处理特定类型的流量等。上添加一个新的队列规则(qdisc, queueing discipline)。是一个非常强大的工具,用于控制网络设备上的数据包队列处理。在 Linux 系统中使用。这个命令的作用是在网络接口。网络接口上的根队列规则。这个命令的作用是删除。

weixin_54703767的博客 1253

linux通信_实时Linux通信

linux通信 实时机器人应用对Linux通信堆栈的评估 本文的内容来自“实时Linux通信:对用于实时机器人应用程序的Linux通信堆栈的评估”, 网址 为 https://arxiv.org/pdf/1808.10821.pdf 。 与Carlos San VicenteGutiérrez,Lander Usategui San Juan和 Irati Zamalloa Ugarte 一...

编程故事的地方 879

Linux信号机制:进程间高效传递事件与操控指令的桥梁

Linux信号机制:进程间高效传递事件与操控指令的桥梁

m0_60259116的博客 1113
上一篇: TC剩余贷款分配规则
下一篇: QUEUEING IN THE LINUX NETWORK STACK
BlueSy2008
博客等级 码龄20年 26粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值