关于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。
?
(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鏈的作用之后,就認為為什么不用下面的算法實現。
?
? ? 我來說說為什么最后還要一個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中的代碼。
?
? ? 你看,<二>和<三>相比是否少了一次調用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等函數都有一個
?
? ? 這個函數實際上也是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的说明[转]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 黑盒测试概念简述,黑盒测试优缺点、黑盒用
- 下一篇: 安装Nvida 显示环境