chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux內(nèi)核UDP收包的效率如何才能提升

Wildesbeast ? 來源:網(wǎng)絡(luò)整理 ? 作者:佚名 ? 2020-04-06 12:03 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

現(xiàn)在很多人都在詬病Linux內(nèi)核協(xié)議棧收包效率低,不管他們是真的懂還是一點(diǎn)都不懂只是聽別人說的,反正就是在一味地懟Linux內(nèi)核協(xié)議棧,他們的武器貌似只有DPDK。

但是,即便Linux內(nèi)核協(xié)議棧收包效率真的很低,這是為什么?有沒有辦法去嘗試著優(yōu)化?而不是動(dòng)不動(dòng)就DPDK。

我們從最開始說起。

Linux內(nèi)核作為一個(gè)通用操作系統(tǒng)內(nèi)核,脫胎于UNIX那一套現(xiàn)代操作系統(tǒng)理論。

但一開始不知道怎么回事將網(wǎng)絡(luò)協(xié)議棧的實(shí)現(xiàn)塞進(jìn)了內(nèi)核態(tài),從此它就一直在內(nèi)核態(tài)了。既然網(wǎng)絡(luò)協(xié)議棧的處理在內(nèi)核態(tài)進(jìn)行,那么網(wǎng)絡(luò)數(shù)據(jù)包必然是在內(nèi)核態(tài)被處理的。無論如何,數(shù)據(jù)包要先進(jìn)入內(nèi)核態(tài),這就涉及到了進(jìn)入內(nèi)核態(tài)的方式:

外部可以從兩個(gè)方向進(jìn)入內(nèi)核-從用戶態(tài)系統(tǒng)調(diào)用進(jìn)入或者從硬件中斷進(jìn)入。

也就是說,系統(tǒng)在任意時(shí)刻,必然處在兩個(gè)上下文中的一個(gè):

進(jìn)程上下文

中斷上下文 (在非中斷線程化的系統(tǒng),也就是任意進(jìn)程上下文)

收包邏輯的協(xié)議棧處理顯然是自網(wǎng)卡而上的,它顯然是在中斷上下文中,而數(shù)據(jù)包往用戶進(jìn)程的數(shù)據(jù)接收處理,顯然是在應(yīng)用程序的進(jìn)程上下文中, 數(shù)據(jù)包通過socket在兩個(gè)上下文中被轉(zhuǎn)接。

在socket層的數(shù)據(jù)包轉(zhuǎn)接處,必然存在著一個(gè)隊(duì)列緩存,這是一個(gè)典型的 生產(chǎn)者-消費(fèi)者 模型,中斷上下文的終點(diǎn)作為生產(chǎn)者將數(shù)據(jù)包入隊(duì),而進(jìn)程上下文作為消費(fèi)者從隊(duì)列消費(fèi)數(shù)據(jù)包:

非常清爽的一個(gè)圖,這個(gè)圖是 兩個(gè)上下文接力處理協(xié)議棧收包邏輯的必然結(jié)果 ,讓我們加入一些實(shí)際必須要考慮的問題后,我們會(huì)發(fā)現(xiàn)這幅圖并不是那么清爽,然后再回過頭看如何來優(yōu)化。

既然兩個(gè)上下文都要在任意可能的時(shí)刻操作同一個(gè)socket進(jìn)行數(shù)據(jù)包的轉(zhuǎn)交,那么必須有一個(gè)同步機(jī)制保護(hù)socket元數(shù)據(jù)以及數(shù)據(jù)包skb本身。

由于Linux內(nèi)核中斷,軟中斷可能處在任意進(jìn)程上下文,唯一的同步方案幾乎就是spinlock了,于是,真正的圖示應(yīng)該是下面的樣子:

現(xiàn)在可以說,類似上面的這種這種保護(hù)是非常必要的,特別是對(duì)于TCP而言。

我們知道,TCP是基于事務(wù)的有狀態(tài)傳輸協(xié)議,而且攜帶復(fù)雜的流控和擁塞控制機(jī)制,這些機(jī)制所依托的就是socket當(dāng)前的一些狀態(tài)數(shù)據(jù),比如inflight,lost,retrans等等,這些狀態(tài)數(shù)據(jù)在發(fā)包和接收ACK/SACK期間會(huì)不斷變化,所以說:

在一個(gè)上下文完成一次事務(wù)傳輸之前,必須鎖定socket狀態(tài)數(shù)據(jù)。

比方說發(fā)包流程。數(shù)據(jù)包的發(fā)送可以出現(xiàn)在兩個(gè)上下文中:

進(jìn)程上下文:系統(tǒng)調(diào)用觸發(fā)的發(fā)包。

中斷上下文:ACK/SACK觸發(fā)的發(fā)包。

任何一個(gè)上下文的發(fā)包過程必須被TCP協(xié)議本身比如擁塞控制,流量控制這些所終止,而不能被中途切換到另一個(gè)上下文中,所以必須鎖定。

問題是,上圖中的鎖定是不是太狠了些,中斷上下文自旋時(shí)間完全取決于進(jìn)程上下文的行文,這不利于軟中斷的快速返回,極大地降低了系統(tǒng)的響應(yīng)度。

于是,需要把鎖的粒度進(jìn)行細(xì)分。Linux內(nèi)核并沒有在橫向上將鎖的粒度做劃分,而是在縱向上,采用兩個(gè)層次的鎖機(jī)制:

我們看到的Linux內(nèi)核在處理收包邏輯時(shí)的backlog,其實(shí)抽象出來就是上面的二級(jí)鎖,它是不是很像Windows的IRQL機(jī)制呢?伴隨著APC,DPC,你可以把暫時(shí)由于高level的IRQL阻滯而無法執(zhí)行的邏輯放入DPC:

由于進(jìn)程上下文對(duì)socket的low鎖占有,中斷上下文將skb排入次level的backlog隊(duì)列,當(dāng)進(jìn)程上下文釋放low鎖的時(shí)候,順序執(zhí)行次level被排入的任務(wù),即處理backlog中的skb。

事實(shí)上這是一種非常常見且通用的設(shè)計(jì),除了Windows的IRQL,Linux中斷的上半部/下半部也是這種基于思想設(shè)計(jì)的。

前面說了,TCP的一次事務(wù)可能非常 復(fù)雜耗時(shí) ,并且必須一次完成,這意味著期間必須持有socket low鎖,以發(fā)包邏輯 tcp_write_xmit 函數(shù)為例,其內(nèi)部循環(huán)發(fā)包,直到受到窗口限制而終止,每一次tcp_transmit_skb返回耗時(shí)3微秒~5微秒,平均4微秒,以每次發(fā)送4個(gè)包為例,在這期間,若使用spinlock,那么中斷上下文的收包路徑將自旋16微秒,16微秒對(duì)于spinlock而言有點(diǎn)久了,于是采用兩級(jí)的lock機(jī)制,非常有效!

backlog隊(duì)列機(jī)制有效降低了中斷上下文的spin時(shí)延,提高了系統(tǒng)的響應(yīng)度,非常不錯(cuò)。

但問題是,UDP有必要這樣嗎?

首先,UDP是無狀態(tài)的,收包和發(fā)包都無需事務(wù),協(xié)議棧對(duì)UDP的處理,從來都是單個(gè)報(bào)文粒度的,因此只需要保護(hù)唯一的socket接收隊(duì)列即可,即 sk_receive_queue 。

enqueue(skb, sk){ spin_lock(sk-》sk_receive_queue-》lock); skb_queue_tail(sk-》sk_receive_queue, skb); spin_unlock(sk-》sk_receive_queue-》lock);}sk_buff dequeue(sk){ spin_lock(sk-》sk_receive_queue-》lock); skb = skb_dequeue(sk-》sk_receive_queue); spin_unlock(sk-》sk_receive_queue-》lock); return skb;}

需要保護(hù)的接收隊(duì)列操作區(qū)間都是指令級(jí)別的時(shí)延,采用一把單一的 sk_receive_queue-》lock 足矣。

確實(shí),在Linux 2.6.25版本內(nèi)核之前,就是這么干的。而自從2.2版本內(nèi)核,TCP就已經(jīng)采用二級(jí)鎖backlog隊(duì)列了。

然而,在2.6.25版本內(nèi)核中,Linux協(xié)議棧的UDP收包路徑,轉(zhuǎn)而采用了兩層鎖的backlog隊(duì)列機(jī)制,和TCP一樣的邏輯:

low_lock_lock(sk){ spin_lock(sk-》higher_level_spin_lock); // 熱點(diǎn)! sk-》low_lock_owned_by_process = 1; spin_unlock(sk-》higher_level_spin_lock);}low_lock_unlock(sk){ spin_lock(sk-》higher_level_spin_lock); sk-》low_lock_owned_by_process = 0; spin_unlock(sk-》higher_level_spin_lock);}udp_rcv(skb) // 中斷上下文{ sk = lookup(。..); spin_lock(sk-》higher_level_spin_lock); // 熱點(diǎn)! if (sk-》low_lock_owned_by_process) { enqueue_to_backlog(skb, sk); } else { enqueue(skb, sk);// 見上面的偽代碼 update_statis(sk); wakeup_process(sk); } spin_unlock(sk-》higher_level_spin_lock);}udp_recv(sk, buff) // 進(jìn)程上下文{ skb = dequeue(sk); // 見上面的偽代碼 if (skb) { copy_skb_to_buff(skb, buff); low_lock_lock(sk); update_statis(sk); low_lock_unlock(sk); dequeue_backlog_to_receive_queue(sk); }}

顯然這非常沒有必要。如果你有多個(gè)線程同時(shí)操作一個(gè)UDP socket,將會(huì)直面這個(gè)熱點(diǎn),但事實(shí)上,你很難遭遇這樣的場(chǎng)景,如果非要說一個(gè),那么DNS服務(wù)器可能首當(dāng)其中。

之所以在2.6.25版本內(nèi)核引入了二級(jí)鎖backlog隊(duì)列,大致是考慮到UDP需要統(tǒng)計(jì)內(nèi)存全局記賬,以防UDP吃盡系統(tǒng)內(nèi)存,可以review一下 sk_rmem_schedule 函數(shù)的邏輯。而在2.6.25版本內(nèi)核之前,UDP的內(nèi)存使用是不記賬的,由于UDP本身沒有任何類似流控,擁塞控制之類的約束機(jī)制,很容易被惡意程序?qū)⑾到y(tǒng)內(nèi)存吃盡。

因此,除了sk_receive_queue需要保護(hù),內(nèi)存記賬邏輯也是需要保護(hù)的,比如累加當(dāng)前skb對(duì)內(nèi)存的占用到全局?jǐn)?shù)據(jù)結(jié)構(gòu)。但即便如此,把這些統(tǒng)計(jì)數(shù)據(jù)的更新都塞入到spinlock的保護(hù)區(qū)域,也還是要比兩級(jí)lock要好。

在我看來,之所以引入二級(jí)鎖backlog機(jī)制來保護(hù)內(nèi)存記賬邏輯,這是在 借鑒 TCP的代碼,或者說 抄代碼 更直接些。這個(gè)攜帶backlog隊(duì)列機(jī)制的UDP收包代碼存在了好多年,一直在4.9內(nèi)核才終結(jié)。

事實(shí)上,僅僅下面的邏輯就可以了:

enqueue(skb, sk){ spin_lock(sk-》sk_receive_queue-》lock); skb_queue_tail(sk-》sk_receive_queue, skb); update_statis(sk); spin_unlock(sk-》sk_receive_queue-》lock);}sk_buff dequeue(sk){ spin_lock(sk-》sk_receive_queue-》lock); skb = skb_dequeue(sk-》sk_receive_queue); update_statis(sk); spin_unlock(sk-》sk_receive_queue-》lock); return skb;}udp_rcv(skb) // 中斷上下文{ sk = lookup(。..); spin_lock(sk-》higher_level_spin_lock); enqueue(skb, sk);// 見上面的偽代碼 spin_unlock(sk-》higher_level_spin_lock);}udp_recv(sk, buff) // 進(jìn)程上下文{ skb = dequeue(sk); // 見上面的偽代碼 if (skb) { copy_skb_to_buff(skb, buff); }}

簡(jiǎn)單直接!Linux內(nèi)核的UDP處理邏輯在4.10版本也確實(shí)去掉了兩級(jí)的lock。恢復(fù)到了2.6.25內(nèi)核版本之前的邏輯。

上面的優(yōu)化帶來了可觀的性能收益,但是卻并不值得炫耀。

因?yàn)樯厦娴膬?yōu)化更像是解決了一個(gè)bug,這個(gè)bug是在2.6.25版本內(nèi)核因?yàn)榻梃bTCP的backlog實(shí)現(xiàn)而引入的,而事實(shí)上,UDP并不需要這種花哨的backlog邏輯。所以說,上面的效果并非優(yōu)化而帶來的效果,而是解了一個(gè)bug帶來的效果。

但是為什么遲至4.10版本才發(fā)現(xiàn)并解決這個(gè)問題的呢?

我想這件事可能跟QUIC有關(guān)。

用得少的邏輯自然就不容易發(fā)現(xiàn)問題,這就好比David Miller在2.6版本內(nèi)核引入IPv6實(shí)現(xiàn)的那幾個(gè)bug,就是因?yàn)镮Pv6用的人少,所以一直在很晚的4.23+版本內(nèi)核才被發(fā)現(xiàn)被解決。對(duì)于UDP,一直到2.6.24版本其實(shí)現(xiàn)都挺好,符合邏輯,2.6.25引入的二級(jí)鎖bug同樣是因?yàn)閁DP本身用的少而沒有被發(fā)現(xiàn)。

在QUIC之前,很少有那種有來有回的持續(xù)全雙工UDP長(zhǎng)連接,基本都是request/response的oneshot類型的連接。然而QUIC卻是類似TCP的全雙工協(xié)議,在數(shù)據(jù)發(fā)送端持續(xù)發(fā)送大塊數(shù)據(jù)的同時(shí),伴隨著的是接收大量的ACK報(bào)文,這顯然和TCP一樣,也是一種反饋控制的方式來驅(qū)動(dòng)數(shù)據(jù)的發(fā)送。

QUIC是有確認(rèn)機(jī)制的,但是處理確認(rèn)卻不是在內(nèi)核進(jìn)行的,內(nèi)核只是一個(gè)快速將確認(rèn)包收到用戶態(tài)QUIC處理進(jìn)程的一個(gè)通路,這個(gè)通路越快越好!

也就是說,QUIC的ACK報(bào)文的接收效率會(huì)影響其數(shù)據(jù)的發(fā)送效率。

隨著QUIC的大規(guī)模部署,人們才開始逐漸關(guān)注其背后UDP的收包效率問題。

擺脫了二級(jí)鎖的backlog隊(duì)列之后,僅僅是為UDP后續(xù)的優(yōu)化掃清了障礙,這才是真正剛剛開始。擺在UDP的內(nèi)核協(xié)議棧收包效率面前的,有一個(gè)現(xiàn)成的靶子,那就是DPDK。

挺煩DPDK的,說實(shí)話,被人天天說的東西都挺煩。不過你得先把內(nèi)核協(xié)議棧的UDP性能優(yōu)化到接近DPDK,再把這種鄙視當(dāng)后話來講才更酷。

由于UDP的處理非常簡(jiǎn)單,因此實(shí)現(xiàn)一個(gè)能和DPDK對(duì)接的UDP用戶態(tài)協(xié)議棧則并不是一件難事。而TCP則相反,它非常復(fù)雜,所以DPDK很少有完整處理TCP端到端邏輯的,大多數(shù)都只是做類似中間節(jié)點(diǎn)DPI這種事。目前都沒有幾個(gè)好用的基于DPDK的TCP實(shí)現(xiàn),但是UDP實(shí)現(xiàn)卻很多。

DPDK的偽粉絲拿UDP說事的,比拿TCP說事,成本要低很多。

好吧,那為什么DPDK處理UDP收包效率那么高?

答案很簡(jiǎn)單, DPDK是在進(jìn)程上下文輪詢接收UDP數(shù)據(jù)包的! 也就是說,它擺脫了兩個(gè)問題:

進(jìn)程上下文和中斷上下文操作共享數(shù)據(jù)的鎖問題。

進(jìn)程上下文和中斷上下文切換導(dǎo)致的cache miss問題。

這兩點(diǎn)其實(shí)也就是 “為什么內(nèi)核協(xié)議棧性能干不過用戶態(tài)協(xié)議棧” 的要點(diǎn)。當(dāng)然,Linux內(nèi)核協(xié)議棧無法擺脫這兩點(diǎn)問題,也就回答了本文的題目中的第一個(gè)問題, “Linux內(nèi)核UDP收包為什么效率低?” 。

不同的上下文異步操作同一份數(shù)據(jù),鎖是必不可少的。關(guān)于鎖的話題已經(jīng)爛大街了。

現(xiàn)在僅就cache來討論,中斷上下文和進(jìn)程上下文之間的切換,也有一個(gè)明顯的case:

中斷上下文中修改了socket的元統(tǒng)計(jì)數(shù)據(jù),該修改會(huì)表現(xiàn)在cache中,然而當(dāng)其wakeup該socket的處理進(jìn)程后,切換到進(jìn)程上下文的recv系統(tǒng)調(diào)用,其也或讀或?qū)戇@個(gè)統(tǒng)計(jì)數(shù)據(jù),伴隨著cache的flush以及cache的一致性同步。

如果這些操作統(tǒng)一在進(jìn)程上下文中進(jìn)行,cache的利用率將會(huì)高效很多。當(dāng)然,回到UDP收包不合理的backlog隊(duì)列機(jī)制,其實(shí)backlog本身存在的目的之一,就是為了讓進(jìn)程上下文去處理,以提高cache的利用率,減少不必要的flush。然而,初衷未必能達(dá)到效果,在傳輸層用backlog將skb推給進(jìn)程上下文去處理,已經(jīng)太晚了,何必不再網(wǎng)卡就給進(jìn)程上下文呢?就像DPDK那樣。

其實(shí)Linux內(nèi)核社區(qū)早就意識(shí)到了這兩點(diǎn),早在3.11版本內(nèi)核中引入的busy poll機(jī)制就是為了解決鎖和切換問題的。busy poll的思想非常簡(jiǎn)單,那就是:

不再需要軟中斷上下文往接收隊(duì)列里“推”數(shù)據(jù)包,而改成自己在進(jìn)程上下文里主動(dòng)從網(wǎng)卡上“拉”數(shù)據(jù)包。

落實(shí)到代碼上,那就是在進(jìn)程上下文的recvmsg函數(shù)中直接調(diào)用napi的收包函數(shù),從ring buffer里拿數(shù)據(jù),自己調(diào)用netif_receive_skb。

如果busy poll總能執(zhí)行,它總是能拉取到自己下一個(gè)需要的數(shù)據(jù)包,那么這基本就是DPDK的效率了,然而和DPDK一樣,這并不是一個(gè)統(tǒng)一的解決方案,輪詢固然對(duì)于收包有收益,但中斷是不能丟的,用CPU的自旋輪詢換取收包效率,這買賣代價(jià)太大,畢竟Linux內(nèi)核并非專職收包的。

當(dāng)然了,也許內(nèi)核態(tài)實(shí)現(xiàn)協(xié)議棧本身就是一種錯(cuò)誤,但這個(gè)話題有點(diǎn)跑偏,畢竟我們就是要優(yōu)化內(nèi)核協(xié)議棧的,而不是放棄它。

現(xiàn)在,我們不能指望busy poll擔(dān)當(dāng)所有的性能問題,仍然要依靠中斷。既然依靠中斷,鎖的問題就是優(yōu)化的重點(diǎn)。

以雙核CPU為例,假設(shè)CPU0專職處理中斷,而收包進(jìn)程則綁定在CPU1上,我們很快能意識(shí)到, CPU0和CPU1對(duì)于每一個(gè)skb的enqueue和dequeue均在爭(zhēng)搶socket的sk_receive_queue的spinlock 。

優(yōu)化措施顯而易見, 將多個(gè)skb聚集起來,一次性入接收隊(duì)列 。顯然,這需要兩個(gè)隊(duì)列:

維護(hù)聚集隊(duì)列:由中斷上下文將skb推入該隊(duì)列。

維護(hù)接收隊(duì)列:進(jìn)程上下文從該隊(duì)列拉取skb。

接收隊(duì)列為空時(shí),交換聚集隊(duì)列和接收隊(duì)列。

這樣,同樣在上述雙核CPU的情況下,只有在上面的第3點(diǎn)的操作中,才需要鎖保護(hù)。

考慮到機(jī)器的CPU并非雙核,可能是任意核,收包進(jìn)程也未必綁定任何CPU,因此上述每一個(gè)隊(duì)列均需要一把鎖保護(hù),無論如何, 和單隊(duì)列相比,雙隊(duì)列情況下,鎖的競(jìng)爭(zhēng)減少了一半!

collect_enqueue(skb, sk){ spin_lock(sk-》sk_collect_queue-》lock); skb_queue_tail(sk-》sk_collect_queue, skb); update_statis(sk); spin_unlock(sk-》sk_collect_queue-》lock);}sk_buff recv_dequeue(sk){ spin_lock(sk-》sk_receive_queue-》lock); skb = skb_dequeue(sk-》sk_receive_queue); update_statis(sk); spin_unlock(sk-》sk_receive_queue-》lock); return skb;}udp_rcv(skb) // 中斷上下文{ sk = lookup(。..); spin_lock(sk-》higher_level_spin_lock); collect_enqueue(skb, sk);// 僅僅往聚集隊(duì)列里推入。 spin_unlock(sk-》higher_level_spin_lock);}udp_recv(sk, buff) // 進(jìn)程上下文{ if (empty(sk-》sk_receive_queue)) { spin_lock(sk-》queues_lock); swap(sk-》sk_receive_queue, sk-》sk_collect_queue); spin_unlock(sk-》queues_lock) } skb = recv_dequeue(sk); // 僅僅從接收隊(duì)列里拉取 if (skb) { copy_skb_to_buff(skb, buff); }}

如此一來,雙隊(duì)列解除了中斷上下文和進(jìn)程上下文之間的鎖競(jìng)爭(zhēng)。

來看一下對(duì)比圖示:

引入雙隊(duì)列后:

即便已經(jīng)很不錯(cuò)了,但是:

中斷上下文中不同CPU可能會(huì)收到同一個(gè)socket的skb,CPU依然會(huì)在聚集隊(duì)列的鎖上蹦跶。

不同的CPU上的進(jìn)程也可能會(huì)處理同一個(gè)socket,本意是合作,卻需要接收隊(duì)列的鎖來將其操作串行化。

沒辦法,通用的操作系統(tǒng)內(nèi)核只能做到這里了,如果要解決以上的問題,就需要按照任何和角色明確綁CPU核心了,然而這也就不再是通用的內(nèi)核了。最終,你會(huì)在內(nèi)核里聞到DPDK的腐臭味,超級(jí)惡心。

對(duì)了,我暫且將雙隊(duì)列區(qū)分為了 聚集隊(duì)列 和 接收隊(duì)列 ,更好的名字可能是 backlog隊(duì)列 和 接收隊(duì)列 。中斷上下文總是操作backlog隊(duì)列,而進(jìn)程上下文在接收隊(duì)列為空時(shí),交換backlog隊(duì)列為接收隊(duì)列。然而,backlog隊(duì)列這個(gè)名字在我看來非常臭名昭著,所以,暫且不用它了。

我想本文應(yīng)該就要結(jié)束了,確實(shí)沒有源碼分析,事實(shí)上,我覺得我寫的這篇要比下面的這種有意思的多,然而可能在網(wǎng)上能找到的基本都是這種 非常詳細(xì)的源碼分析:

。.. bh_lock_sock(sk); // 鎖定住sk if (!sock_owned_by_user(sk)) // 判斷sk是不是被用戶進(jìn)程所擁有,如果沒有被擁有的話。 rc = __udp_queue_rcv_skb(sk, skb); // 直接調(diào)用__udp_queue_rcv_skb else if (sk_add_backlog(sk, skb, sk-》sk_rcvbuf)) { //否則調(diào)用sk_add_backlog將skb放入backlog bh_unlock_sock(sk); // 如果失敗,解鎖sk,直接丟包 goto drop; } bh_unlock_sock(sk); // 解鎖sk return rc; // 返回rc 。..

哈哈…

我為什么沒有談UDP的GRO,LRO機(jī)制,因?yàn)樘煌ㄓ昧恕5橇硪环矫?,如果?yīng)用程序加以稍微支持,UDP的GRO,LRO將會(huì)帶來非??捎^的收益,別忘了,內(nèi)核只是UDP報(bào)文的一個(gè)通路即可,既然是通路,它便不包含處理邏輯,越快通過,越好。如果你在乎高吞吐,那么就GRO唄,如下:

UDP的通用L4 GRO相當(dāng)于一個(gè)非常簡(jiǎn)單的5層協(xié)議,應(yīng)用程序按照len字段稍加解析拆分即可,這將極大減少系統(tǒng)調(diào)用的次數(shù),減少上下文切換帶來的cache miss損耗。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    88

    文章

    11806

    瀏覽量

    219493
  • Socket
    +關(guān)注

    關(guān)注

    1

    文章

    214

    瀏覽量

    37017
  • UDP
    UDP
    +關(guān)注

    關(guān)注

    0

    文章

    335

    瀏覽量

    35517
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    如何理解Linux內(nèi)核中的PCIe驅(qū)動(dòng)

    我們習(xí)慣了用 Verilog 去死磕 PCIe 的底層協(xié)議狀態(tài)機(jī)。但一旦越過硬件邊界來到操作系統(tǒng)層面,Linux 內(nèi)核是如何接管并驅(qū)動(dòng)這些 PCI/PCIe 設(shè)備的呢?由于不同的 CPU 架構(gòu)實(shí)現(xiàn)了
    的頭像 發(fā)表于 04-11 17:22 ?1193次閱讀

    Linux內(nèi)核驅(qū)動(dòng)開發(fā)的技術(shù)核心精要

    嵌入式Linux驅(qū)動(dòng)開發(fā)是連接硬件與操作系統(tǒng)的關(guān)鍵環(huán)節(jié)。隨著內(nèi)核演進(jìn)(如Linux 6.13)和硬件復(fù)雜度提升,開發(fā)者需掌握并發(fā)控制、中斷分層、內(nèi)存管理、設(shè)備樹、調(diào)試工具等核心知識(shí)。本
    發(fā)表于 03-10 13:56

    Linux內(nèi)核的“心跳”:jiffies如何為系統(tǒng)計(jì)時(shí)?

    Linux 內(nèi)核的世界里,有一個(gè)默默工作的 "計(jì)時(shí)器"——jiffies。它不像我們手機(jī)上的時(shí)鐘那樣顯示年月日,卻掌控著內(nèi)核中絕大多數(shù)時(shí)間相關(guān)的操作:從進(jìn)程調(diào)度到設(shè)備驅(qū)動(dòng)的定時(shí)檢查,都離不開它的身影。
    的頭像 發(fā)表于 02-04 16:27 ?913次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>的“心跳”:jiffies如何為系統(tǒng)計(jì)時(shí)?

    深入RK3588內(nèi)核:rockchip_linux_defconfig的作用與調(diào)試價(jià)值

    在 RK3588 芯片的 Linux 開發(fā)中,有一個(gè)文件始終是開發(fā)者繞不開的核心 ——kernel/arch/arm64/configs/rockchip_linux_defconfig。無論是首次
    的頭像 發(fā)表于 02-03 15:56 ?1349次閱讀
    深入RK3588<b class='flag-5'>內(nèi)核</b>:rockchip_<b class='flag-5'>linux</b>_defconfig的作用與調(diào)試價(jià)值

    Linux系統(tǒng)內(nèi)核參數(shù)調(diào)優(yōu)實(shí)戰(zhàn)指南

    Linux 內(nèi)核參數(shù)調(diào)優(yōu)是系統(tǒng)性能優(yōu)化的核心環(huán)節(jié)。隨著云原生架構(gòu)的普及和硬件性能的飛速提升,默認(rèn)的內(nèi)核參數(shù)配置往往無法充分發(fā)揮系統(tǒng)潛力。在高并發(fā) Web 服務(wù)、大數(shù)據(jù)處理、容器化部署等
    的頭像 發(fā)表于 01-28 14:27 ?661次閱讀

    【「Linux 設(shè)備驅(qū)動(dòng)開發(fā)(第 2 版)」閱讀體驗(yàn)】Linux內(nèi)核開發(fā)基礎(chǔ)

    感謝電子發(fā)燒友論壇提供的《Linux設(shè)備驅(qū)動(dòng)開發(fā)(第2版)》閱讀機(jī)會(huì),測(cè)評(píng)將從Linux內(nèi)核開發(fā)基礎(chǔ)、Linux內(nèi)核平臺(tái)抽象和設(shè)備驅(qū)動(dòng)程序、
    發(fā)表于 01-12 22:45

    深入Linux內(nèi)核:進(jìn)程調(diào)度的核心邏輯與實(shí)現(xiàn)細(xì)節(jié)

    ,背后都離不開內(nèi)核調(diào)度算法的精準(zhǔn)操控。今天,我們就從優(yōu)先級(jí)、調(diào)度算法、時(shí)間片分配到底層實(shí)現(xiàn),全方位拆解Linux內(nèi)核進(jìn)程調(diào)度的核心邏輯。 一、進(jìn)程調(diào)度的“身份標(biāo)識(shí)”:優(yōu)先級(jí)與分類 要理解調(diào)度邏輯,首先得搞懂:進(jìn)程憑什么“插隊(duì)”?
    的頭像 發(fā)表于 12-24 07:05 ?4549次閱讀
    深入<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>:進(jìn)程調(diào)度的核心邏輯與實(shí)現(xiàn)細(xì)節(jié)

    TCP和UDP的區(qū)別

    流。UDP 的數(shù)據(jù)傳輸是基于數(shù)據(jù)報(bào)的,這是因?yàn)閮H僅只是繼承了 IP 層的特性,而 TCP 為了維護(hù)狀態(tài),將一個(gè)個(gè) IP 變成了字節(jié)流。
    發(fā)表于 12-09 07:24

    基于 DR1M90 的 Linux-RT 內(nèi)核開發(fā):從編譯配置到 GPIO / 按鍵應(yīng)用實(shí)現(xiàn)(1)

    本手冊(cè)由創(chuàng)龍科技研發(fā),針對(duì) DR1M90,詳述 Linux-RT 實(shí)時(shí)內(nèi)核開發(fā):含實(shí)時(shí)性測(cè)試(LinuxLinux-RT 對(duì)比、CPU 空載 / 滿負(fù)荷 / 隔離狀態(tài)測(cè)試)、
    的頭像 發(fā)表于 12-02 10:38 ?1289次閱讀
    基于 DR1M90 的 <b class='flag-5'>Linux</b>-RT <b class='flag-5'>內(nèi)核</b>開發(fā):從編譯配置到 GPIO / 按鍵應(yīng)用實(shí)現(xiàn)(1)

    Linux內(nèi)核printk日志級(jí)別全解析:從參數(shù)解讀到實(shí)操配置

    一、開篇:一個(gè)命令引出的核心問題 在?Linux?終端執(zhí)行?cat /proc/sys/kernel/printk,你可能會(huì)看到這樣的輸出: 這串?dāng)?shù)字不是隨機(jī)的,而是內(nèi)核日志系統(tǒng)的“核心配置開關(guān)
    的頭像 發(fā)表于 11-20 15:54 ?1927次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>printk日志級(jí)別全解析:從參數(shù)解讀到實(shí)操配置

    deepin亮相2025中國Linux內(nèi)核開發(fā)者大會(huì)

    11 月 1 日,第二十屆中國 Linux 內(nèi)核開發(fā)者大會(huì)(CLK)在深圳舉辦。CLK 作為國內(nèi) Linux 內(nèi)核領(lǐng)域極具影響力的峰會(huì),由清華大學(xué)、Intel、華為、阿里云、富士通南大
    的頭像 發(fā)表于 11-05 17:59 ?918次閱讀

    迅為3568開發(fā)板從零學(xué)習(xí)Linux驅(qū)動(dòng)開發(fā):迅為一站式資料如何讓我效率翻倍

    迅為3568開發(fā)板從零學(xué)習(xí)Linux驅(qū)動(dòng)開發(fā):迅為一站式資料如何讓我效率翻倍
    的頭像 發(fā)表于 11-05 11:16 ?519次閱讀
    迅為3568開發(fā)板從零學(xué)習(xí)<b class='flag-5'>Linux</b>驅(qū)動(dòng)開發(fā):迅為一站式資料<b class='flag-5'>包</b>如何讓我<b class='flag-5'>效率</b>翻倍

    Linux內(nèi)核參數(shù)調(diào)優(yōu)方案

    在高并發(fā)微服務(wù)環(huán)境中,網(wǎng)絡(luò)性能往往成為K8s集群的瓶頸。本文將深入探討如何通過精細(xì)化的Linux內(nèi)核參數(shù)調(diào)優(yōu),讓你的K8s節(jié)點(diǎn)網(wǎng)絡(luò)性能提升30%以上。
    的頭像 發(fā)表于 08-06 17:50 ?1139次閱讀

    如何配置和驗(yàn)證Linux內(nèi)核參數(shù)

    Linux系統(tǒng)運(yùn)維和性能優(yōu)化中,內(nèi)核參數(shù)(sysctl)的配置至關(guān)重要。合理的參數(shù)調(diào)整可以顯著提升網(wǎng)絡(luò)性能、系統(tǒng)穩(wěn)定性及資源利用率。然而,僅僅修改參數(shù)是不夠的,如何驗(yàn)證這些參數(shù)是否生效同樣關(guān)鍵。
    的頭像 發(fā)表于 05-29 17:40 ?1339次閱讀

    揭秘,瑞芯微全系擁抱Linux 6.1內(nèi)核的底層邏輯

    近期,瑞芯微(Rockchip)基本完成了旗下產(chǎn)品Linux6.1BSP內(nèi)核更新,引發(fā)了不小的行業(yè)熱議。除了低端RK3506依舊使用Buildroot構(gòu)建系統(tǒng)外,RK3588、RK3576
    的頭像 發(fā)表于 05-16 08:31 ?1479次閱讀
    揭秘,瑞芯微全系擁抱<b class='flag-5'>Linux</b> 6.1<b class='flag-5'>內(nèi)核</b>的底層邏輯