进架为数据包是什么意思的一半啥意思

与网络数据包是什么意思的发送鈈同网络收包是异步的的。由于你不确定谁会在什么时候突然发一个网络包给你因此这个网络收包逻辑事实上包括两件事:


1.数据包是什么意思到来后的通知
2.收到通知并从数据包是什么意思中获取数据

这两件事发生在协议栈的两端。即网卡/协议栈边界以及协议栈/应用边界:

网卡通知数据包是什么意思到来中断协议栈收包;

协议栈将数据包是什么意思填充socket队列,通知应用程序有数据可读应用程序负责接收数据。


本文就来介绍一下关于这两个边界的这两件事是怎么一个细节关乎网卡中断,NAPI网卡poll,select/poll/epoll等细节并假设你已经大约懂了这些。

網卡/协议栈边界的事件

网卡在数据包是什么意思到来的时候会触发中断然后协议栈就知道了数据包是什么意思到来事件。接下来怎么收包全然取决于协议栈本身这就是网卡中断处理程序的任务,当然也能够不採用中断的方式,而是採用一个单独的线程不断轮询网卡是否有数据包是什么意思的到来可是这样的方式过于消耗CPU。做过多的无用功因此基本被弃用。像这样的异步事件基本都是採用中断通知的方案。综合整个收包逻辑大致能够分为下面两种方式


a.每个数据包是什么意思到来即中断CPU。由CPU调度中断处理程序进行收包处理收包邏辑又分为上半部和下半部,核心的协议栈处理逻辑在下半部完毕
b.数据包是什么意思到来,中断CPUCPU调度中断处理程序而且关闭中断响应,调度下半部不断轮询网卡收包完毕或者达到一个阀值后,又一次开启中断

当中的方式a在数据包是什么意思持续高速到达的时候会造荿非常大的性能损害,因此这样的情况下一般採用方式b这也是Linux NAPI採用的方式。

关于网卡/协议栈边界所发生的事件不想再说很多其他了,甴于这会涉及到非常多硬件的细节比方你在NAPI方式下关了中断后,网卡内部是怎么缓存数据包是什么意思的另外考虑到多核处理器的情形。是不是能够将一个网卡收到的数据包是什么意思中断到不同的CPU核心呢那么这就涉及到了多队列网卡的问题,而这些都不是一个普通嘚内核程序猿所能驾驭的你要了解很多其他的与厂商相关的东西,比方Intel的各种规范各种让人看到晕的手冊...


因此。为了更easy理解我决定茬还有一个边界。即协议栈栈/应用边界来描写叙述相同的事情而这些基本都是内核程序猿甚至应用程序猿所感兴趣的领域了,为了使后媔的讨论更easy进行我将这个协议栈栈/应用边界重命名为协议栈/socket边界,socket隔离了协议栈和应用程序它就是一个接口,对于协议栈它能够代表应用程序。对于应用程序它能够代表协议栈。当数据包是什么意思到来的时候会发生例如以下的事情:


1).协议栈将数据包是什么意思放入socket的接收缓冲区队列,并通知持有该socket的应用程序;
2).CPU调度持有该socket的应用程序将数据包是什么意思从接收缓冲区队列中取出,收包完毕

洳上图所看到的,每个socket的收包逻辑都包括下面两个要素

协议栈处理完毕的数据包是什么意思要排入到的队列应用程序被唤醒后要从该队列中读取数据。

与该socket相关的应用程序假设没有数据可读能够在这个队列上睡眠。一旦协议栈将数据包是什么意思排入socket的接收队列将唤醒该睡眠队列上的进程或者线程。

在有运行流操作socket的元数据的时候必须锁定socket,注意接收队列和睡眠队列并不须要该锁来保护。该锁所保护的是相似socket缓冲区大小改动TCP按序接收之类的事情。

这个模型非常easy且直接和网卡中断CPU通知网络上有数据包是什么意思到来须要处理一樣,协议栈通过这样的方式通知应用程序有数据可读在继续讨论细节以及select/poll/epoll之前,先说两个无关的事后面就不再说了,仅仅是由于它们楿关所以仅仅是提一下而已。不会占用大量篇幅


相似TCP accpet逻辑这样,对于大型webserver而言基本上都是有多个进程或者线程同一时候在一个Listen socket上进荇accept,假设协议栈将一个clientsocket排入了accept队列是将这些线程全部唤醒还是仅仅唤醒一个呢?假设是全部唤醒非常显然。仅仅有一个线程会抢到这個socket其他的线程抢夺失败后继续睡眠,能够说是被白白唤醒了这就是经典的TCP惊群。因此产生了一种排他式的唤醒也就是说仅仅唤醒睡眠队列上的第一个线程,然后退出wakeup逻辑不再唤醒后面的线程。这就避免了惊群

       这个话题在网上的讨论早就已经汗牛充栋,可是细致想┅下就会发现排他唤醒依旧有问题它会大大降低效率。

为什么这么说呢由于协议栈的唤醒操作和应用程序的实际Accept操作之间是全然异步嘚。除非在协议栈唤醒应用程序的时候应用程序恰好堵塞在Accept上,不论什么人都不能保证当时应用程序在干什么举一个简单的样例。在哆核系统上协议栈方面同一时候来了多个请求,而且也恰恰有多个线程等待在睡眠队列上假设能让这多个协议栈运行流同一时候唤醒這多个线程该有多好,可是由于一个socket仅仅有一个Accept队列因此对于该队列的排他唤醒机制基本上将这个畅想给打回去了。唯一一个accpet队列的排叺/取出的带锁操作让整个流程串行化了全然丧失了多核并行的优势。因此REUSEPORT以及基于此的FastTCP就出现了

(今天周末。细致研究了Linux kernel 4.4版本号带来的哽新真的让人眼前一亮啊,后面我会单独写一篇文章来描写叙述)

起初在了解到google的reuseport之前我个人也做过一个相似的patch,当时的想法正是来自於与多队列网卡的类比既然一块网卡能够中断多个CPU。一个socket上的数据可读事件为什么不能中断多个应用程序呢然而socket API早就已经固定死了,這对我的想法造成了打击由于一个socket就是一个文件描写叙述符。表示一个五元组(非connect UDP的socket以及Listen tcp除外)。协议栈的事件恰恰仅仅跟一个五元组相關...因此为了让想法可行仅仅能在socket API之外做文章,那就是同意多个socket绑定相同的IP地址/源port对然后依照源IP地址/port对的HASH值来区分流量的路由,这个想法本人也实现了事实上跟多队列网卡是一个思想。全然一致的多队列网卡不也是依照不同五元组(或者N元组?咱不较真儿)的HASH值来中断不哃的CPU核心的吗细致想想当时的这个移植太TMD帅了。然而看到google的reuseport patch就认为自己做了无用功又一次造了轮子...于是就想解决Accept单队列的问题,既然巳经多核时代了为什么不在每个CPU核心上保持一个accept队列呢?应用程序的调度让schedule子系统去考虑吧...这次没有犯傻于是看到了新浪的FastTCP方案。

好叻插曲已经说完,接下来该细节了

接收队列的管理事实上非常easy,就是一个skb链表协议栈将skb插入到链表的时候先lock住队列本身,然后插入skb然后唤醒socket睡眠队列上的线程。接着线程加锁获取socket接收队列上skb的数据就是这么简单。

后来的版本号都是这个基础版本号的优化版本号先后经历了两次的优化。

接收路径优化1:引入backlog队列

考虑到复杂的细节比方依据收到的数据改动socket缓冲区大小时。应用程序在调用recv例程时须偠对整个socket进行锁定在复杂的多核CPU环境中,有多个应用程序可能会操作同一个socket有多个协议栈运行流也可能会往同一个socket接收缓冲区排入skb[详凊请參考《

》],因此锁的粒度范围自然就变成了socket本身在应用程序持有socket的时候。协议栈由于可能会在软中断上下文运行是不可睡眠等待嘚,为了使得协议栈运行流不至于因此而自旋堵塞引入了一个backlog队列。协议栈在应用程序持有socket的时候仅仅须要将skb排入backlog队列就能够返回了,那么这个backlog队列终于由谁来处理呢

       引入backlog队列后,单一的接收队列变成了一个两阶段的接力队列相似流水线作业那样。这样不管如何协議栈都不用堵塞等待协议栈假设不能立即将skb排入接收队列。那么这件事就由socket锁定者自己来完毕等到它放弃锁定的时候这件事就可以进荇。操作例程例如以下:

能够看到所谓的socket锁,并非一把简单的自旋锁而是在不同的路径有不同的锁定方式,总之仅仅要能保证socket的元數据受到保护,方案都是合理的于是我们看到这是一个两层锁的模型。

两层锁定的lock框架

啰嗦了这么多事实上我们能够把上面最后的那個序列总结成一个更为抽象通用的模式,在某些场景下能够套用

如今就描写叙述一下这个模式。

X.LOCK-自旋锁用于锁定不可睡眠路径以及保護标记锁
X.FLAG-标记锁,用来锁定可睡眠路径


Sleep类的锁定/解锁逻辑:

对于socket收包逻辑事实上就是将skb插入接收队列并唤醒socket的睡眠队列填充到上述的direct_func中僦可以。同一时候delay_func的任务就是将skb插入到backlog队列

       该抽象出来的模型基本就是一个两层锁逻辑,自旋锁在可睡眠路径仅仅用来保护标记位可睡眠路径使用标记位来锁定而不是使用自旋锁本身,标记位的改动被自旋锁保护这个非常快的改动操作取代了慢速的业务逻辑处理路径(仳方socket收包...)的全然锁定。这样就大大降低了竞态带来的CPU时间的自旋开销

最近我在实际的一个场景中就採用了这个模型,非常不错效果也嫃的还好,因此特意抽象出了上述的代码
引入这个两层锁解放了不可睡眠路径的操作,使其在可睡眠路径的task占有一个socket期间仍然能够将数據包是什么意思排入到backlog队列而不是等待可睡眠路径task解锁然而有的时候可睡眠路径上的逻辑也不是那么慢,假设它不慢甚至非常快,锁萣时间非常短那么是不是就能够直接跟不可睡眠路径去争抢自旋锁了呢?这正是引入可睡眠路径fast lock的契机

进程/线程上下文中的socket处理逻辑茬满足下列情况的前提下能够直接与内核协议栈竞争该socket的自旋锁:


b.当前没有其他进程/线程上下文中的socket处理逻辑正在处理这个socket。

满足以上条件的说明这是一个单纯的环境,竞争者地位对等那么非常显然的一个问题就是谁来处理backlog队列的问题,这个问题事实上不是问题由于這样的情况下backlog就用不到了,操作backlog必须持有自旋锁socket在fast lock期间也是持有自旋锁的。两个路径全然相互排斥!

因此上述条件a就极其重要假设在臨界区内出现了大的延迟,会造成协议栈路径过度自旋新的fast lock框架例如以下:

之所以上述代码那么复杂而不是仅仅的spin_lock/spin_unlock。是由于假设X.FLAG为1说奣该socket已经在处理了,比方堵塞等待

以上就是在协议栈/socket边界上的异步流程的队列和锁的整体架构。总结一下包括5个要素:

有了这个框架。协议栈和socket之间就能够安全异步地进行网络数据的交接了假设你细致看,而且对Linux 2.6内核的wakeup机制有足够的了解且有一定的解耦合的思想,峩想应该能够知道select/poll/epoll是如何一种工作机制了

关于这个我想在本文的第二部分描写叙述,我认为仅仅要对基础概念有足够的理解且能够融會贯通。非常多东西都是能够仅仅靠想而推导出来的

在Linux的协议栈实现中,skb表示一个数据包是什么意思一个skb能够属于一个socket或者协议栈,泹不能同一时候属于两者一个skb属于协议栈指的是它不和不论什么一个socket相关联,它仅对协议栈本身负责假设一个skb属于一个socket,就意味着它巳经和一个socket进行了绑定全部的关于它的操作,都要由该socket负责


       Linux为skb提供了一个destructor析构回调函数,每当skb被赋予新的属主的时候会调用前一个属主的析构函数并被指定一个新的析构函数。我们比較关注的是skb从协议栈到socket的这最后一棒在将skb排入到socket接收队列之前。会调用下面的函数:

当中skb_orphan主要是回调了前一个属主赋予该skb的析构函数然后为其指定一个新的析构回调函数sock_rfree。在skb_set_owner_r调用完毕后该skb就正式进入socket的接收队列了:

朂后通过调用sk_data_ready来通知睡眠在socket睡眠队列上的task数据已经被排入接收队列,事实上就是一个wakeup操作然后协议栈就返回。

非常显然接下来关于该skb嘚全部处理均在进程/线程上下文中进行了,等到skb的数据被取出后这个skb不会返回给协议栈。而是由进程/线程自行释放因此在其destructor回调函数sock_rfreeΦ,主要做的就是把缓冲区空间还给系统主要做两件事:

协议数据包是什么意思内存用量的统计和限制

内核协议栈仅仅是内核的一个子系统。且其数据来自本机之外数据来源并不受控,非常easy受到DDos攻击因此有必要限制一个协议的整体内存用量,比方全部的TCP连接仅仅能用10M嘚内存这类Linux内核起初仅仅针对TCP做统计。后来也增加了针对UDP的统计限制在配置上体现为几个sysctl參数:

以上的每一项三个值中,含义例如以丅:

第一个值mem[0]:表示正常值凡是内存用量低于这个值时,都正常;

第二个值mem[1]:警告值凡是高于这个值。就要着手紧缩方案了;

第三个徝mem[2]:不可逾越的界限高于这个值,说明内存使用已经超限了数据要丢弃了。

注意这些配置值是针对单独协议的。而sockopt中配置的recvbuff配置的昰针对单独一条连接的缓冲区限制大小两者是不同的。内核在处理这个协议限额的时候为了避免频繁检測,採用了预分配机制第一佽即便仅仅是来了一个1byte的包。也会为其透支一个页面的内存限额这里并没有实际进行内存分配。由于实际的内存分配在skb生成以及IP分片重組的时候就已经确定了这里仅仅是将这些值累加起来,检測一下是否超过限额而已因此这里的逻辑仅仅是一个加减乘除的过程,除了計算过程消耗的CPU之外并没有消耗其他的机器资源。


proto.memory_allocated:每个协议一个表示当前该协议在内核socket缓冲区里面一共已经使用了多少内存存放skb;
skb.truesize:该skb结构体本身的大小以及其数据大小的总和;

skb即将进入socket的接收队列前夕的累加例程:

协议缓冲区回收时期(会在释放skb或者过期删除skb时调用):


本文的第一部分到此已经结束,第二部分将着重描写叙述selectpoll,epoll的逻辑

}

1很多手机游戏是需要一些大型圖片、音乐、数据库支持,这就是数据包是什么意思

2,推荐您通过电脑管家下载游戏里面的游戏都是经过专业测试人员检测过的,可鉯保证无毒

3,电脑管家下载地址:

4下载好后打开电脑管家——软件管理——安卓游戏,这里收录了上百万款安卓游戏选择您喜欢的進行下载即可,下载完成后将手机通过数据线连接到电脑上点击下载后电脑管家会自动将数据包是什么意思和主程序,自动为您安装到掱机中

下图例如:真实赛车3游戏。

如果还有其他疑问和问题欢迎再次来进行提问,我们将尽全力为您解答疑难

}

我要回帖

更多关于 数据包是什么意思 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信