日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

关于ptype_all和pypte_base中的pt_prev的说明[转]

發布時間:2025/3/15 编程问答 13 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于ptype_all和pypte_base中的pt_prev的说明[转] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

不知道原帖,我是從這里看到了,解決了迷惑我很久的疑問,抄過來。

看見noble_shi兄弟"關于net_rx_action函數的若干問題"貼中關于pt_prev的問題, 本來想在論壇上找到一個相關的帖子的鏈接告訴他。但是發現咱們論壇上關于pt_prev的討論要么沒有說明,要么理解的偏差,甚至是錯誤。而且關于pt_prev的提問很多。故寫了以下內容。

? ? 不過本人水平有限,難免說錯。請執教getmoon@163.com

? ? 結論:pt_prev使用的原因是為了減少一次kfree_skb的調用,提高效率。

? ? 如果有異議的請往下看。如果你對skb非常了解,那么請直接看<三>, 否則請一步一步往下看。

<一>相關知識
在講pt_prev的作用之前, 咱們先說明以下的東西。
(1)alloc_skb中初始化skb->users計數為1。

struct sk_buff( ) { ....atomic_set(&skb->users, 1); ... }

?

(2)kfree_skb中如果計數skb->users不為1則不會釋放skbuff 。

static inline void kfree_skb(struct sk_buff *skb) { if (atomic_read(&skb->users) == 1 || atomic_dec_and_test(&skb->users)) __kfree_skb(skb); }

?

當引用數為1或者引用數減1等于零時, 回收包緩沖。

(3)linux內核網絡協議棧中到本機的skb包是在上層協議中釋放的。

<二>實現ptype_base和ptype_all鏈

? ? 講了上面的東西后咱們來看ptype_base及ptype_all鏈相關的東西。這兩個鏈的作用在這里就不講了。 因為有了上面的東西, 所以涉及到一個skbuff共享的問題, 如果都用skb_clone或者skb_copy,那么性能將是很低的。 所以在linux中使用了skb共享的計數,就是用skb->users計數來計算共享的地方。
許多人理解了ptype_all和ptype_base鏈的作用之后,就認為為什么不用下面的算法實現。

for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) {if (ptype->type == type && (!ptype->dev || ptype->dev == skb->dev)) {atomic_inc(&skb->users);ptype->func(skb, skb->dev, ptype);} } kfree_skb(skb);

?

? ? 我來說說為什么最后還要一個kfree_skb。在進入這個for循環之前,skb->users的計數為1,每進入一個ptype->fun函數之前都會加,并且在每個ptype->fun函數里面都會有kfree_skb函數(會減users),但是并沒有真正的把skb釋放掉。還記得剛開始說明中kfree_skb里面的atomic_dec_and_test(&skb->users)嗎。 所以atomic_inc(&skb->users);ptype->func(skb, skb->dev, ptype);兩句代碼執行之后并沒有改變skb->users的計數,還是1。所以這樣可以在for循環中循環好幾次, 無論幾個ptype->func都可以共享這個skb。退出for循環之后, skb->users還是1,并且之前并沒有真正的釋放掉內存。因此你要調用kfree_skb(skb) 來釋放內存。
? ? 再說明一下另外一個問題,如果for循環就調用了ptype->func函數一次的話,那么在整個包的流程中,是調用了kfree_skb兩次。 一次在ptype->func函數中,第二次是在for循環之后, 就是上面代碼中的kfree_skb 。
說了上面的這個例子之后, 如果你現在知道了為什么用pt_prev來提交效率,那么你就不用往下看了。

<三> 利用pt_prev來提高效率

? ? 理解了上面的內容之后,咱們來看看2.4中的代碼。

for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) {if (ptype->type == type && (!ptype->dev || ptype->dev == skb->dev)) {if (pt_prev) {if (!pt_prev->data)deliver_to_old_ones(pt_prev, skb, 0);else {/*到這里,那么pt_prev指針不為空,ptype(當前的)不為空,那么肯定要共享一次了,所以加1*/atomic_inc(&skb->users);pt_prev->func(skb,skb->dev, pt_prev);/*執行上面的函數之后,會在里面減1。所以相對來說,上面兩句代碼執行之后并沒有對skb->users的值進行影響。*/}}pt_prev = ptype; } }/*現在skb->users的計數還是為1*/ if (pt_prev) {if (!pt_prev->data)deliver_to_old_ones(pt_prev, skb, 1);else/*在這里就沒有用atomic_inc(&skb->users);因為到這里,skb->users就為1,并且這里是最后一次,所以不用加1,那么skb就直接在下面的pt_prev->func(skb, skb->dev, pt_prev);函數中釋放了。*/pt_prev->func(skb, skb->dev, pt_prev); } else{/*到這里,已經沒有對skb進行操作的了。所以必須調用kfree_skb把skb釋放掉。*/kfree_skb(skb); }

?


? ? 你看,<二>和<三>相比是否少了一次調用kfree_skb呢。

? ? 到現在, 你是否理解了為什么么用pt_prev了。
? ? 你是否在為那些家伙的高深之處而感慨那。
? ? anything i can help u , please email to : getmoon@163.com

后續討論
ID:rainfall
? ? 今天我仔細看了一下linux2.2.x的net_bh,我認為pt_prev的作用是減少一次skb_clone(當然也少一次kfree_skb)。得出這個結論的理由是:每次在處理skbuff時,相關的處理都會復制一次skbuff的頭。如果鏈表上有n個元素,就要復制n次,然后還有釋放n次。最后還要釋放結構本身。但是如果只復制n-1次,最后處理的就是數據本身(引用計數為1)。這樣會少復制一次。不過getmoon的說法也沒錯,只是我覺得從復制的角度看,可能更能體現
出高效的主題。畢竟,釋放并不花什么時間。
ID:getmoon
? ? 實際上是這樣的,2.2的net_bh里面也采用了這個pt_prev。 它的功能還是如我所言。
兄弟看見的是在調用每個pt->func之前clone了一個。 實際上這個clone在2.4里面并沒有去掉。 只是把它移動每個具體的pt->funct里面。 你可以看arp_rcv , ip_rcv等函數都有一個

if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)goto out_of_mem;

?


? ? 這個函數實際上也是clone一個。而2.2的每個pt->func如arp_rcv , ip_rcv里面都是沒有的。 因為在調用pt->func之前就clone了。所以2.4的做法是實際上把skb_clone往后移動了。 為什么呢。我想這個還是重效率上考慮的。
? ? 我想作者的想法是:如果在pt->func函數里面根本沒有必要skb_clone一下, 我為什么
在硬給它clone一個呢。如果呢需要新的skb頭,那么呢自己clone去。 因為可能有的人不需要。

轉載于:https://www.cnblogs.com/4a8a08f09d37b73795649038408b5f33/p/11545031.html

總結

以上是生活随笔為你收集整理的关于ptype_all和pypte_base中的pt_prev的说明[转]的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。