亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 14990 | 回復(fù): 5
打印 上一主題 下一主題

關(guān)于ptype_all和pypte_base中的pt_prev的說明[轉(zhuǎn)] [復(fù)制鏈接]

論壇徽章:
36
IT運維版塊每日發(fā)帖之星
日期:2016-04-10 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-04-16 06:20:0015-16賽季CBA聯(lián)賽之廣東
日期:2016-04-16 19:59:32IT運維版塊每日發(fā)帖之星
日期:2016-04-18 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-04-19 06:20:00每日論壇發(fā)貼之星
日期:2016-04-19 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-04-25 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-06 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-08 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-13 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-28 06:20:00每日論壇發(fā)貼之星
日期:2016-05-28 06:20:00
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2010-03-27 17:50 |只看該作者 |正序瀏覽
本帖最后由 Godbach 于 2010-03-27 17:58 編輯

【Godbach注】
論壇中也經(jīng)常有網(wǎng)友問到這個問題,pt_prev在ptype_all和pypte_base中的作用是什么。我在LinuxForum上發(fā)現(xiàn)了一篇對該問題解釋的精華帖。這里轉(zhuǎn)載過來,并將原帖中兩個關(guān)鍵的回帖一并貼了過來,以饗大家。原文是有ID為getmoon發(fā)表于LinuxForum上的,連接為:http://www.linuxforum.net/forum/ ... &page=&view=&sb=&o=。感謝getmoon的精彩分析。

                                                                                                                                                                                                                                           --Mar 27,2010


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

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

    結(jié)論:pt_prev使用的原因是為了減少一次kfree_skb的調(diào)用,提高效率。

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

<一>相關(guān)知識
在講pt_prev的作用之前, 咱們先說明以下的東西。
(1)alloc_skb中初始化skb->users計數(shù)為1。
  1. struct sk_buff( )
  2. {
  3. ....
  4.     atomic_set(&skb->users, 1);
  5. ...
  6. }
復(fù)制代碼
(2)kfree_skb中如果計數(shù)skb->users不為1則不會釋放skbuff 。
  1. static inline void kfree_skb(struct sk_buff *skb)
  2. {
  3. if (atomic_read(&skb->users) == 1 || atomic_dec_and_test(&skb->users))
  4. __kfree_skb(skb);
  5. }
復(fù)制代碼
當(dāng)引用數(shù)為1或者引用數(shù)減1等于零時, 回收包緩沖。

(3)linux內(nèi)核網(wǎng)絡(luò)協(xié)議棧中到本機的skb包是在上層協(xié)議中釋放的。

<二>實現(xiàn)ptype_base和ptype_all鏈

    講了上面的東西后咱們來看ptype_base及ptype_all鏈相關(guān)的東西。這兩個鏈的作用在這里就不講了。 因為有了上面的東西, 所以涉及到一個skbuff共享的問題, 如果都用skb_clone或者skb_copy,那么性能將是很低的。 所以在linux中使用了skb共享的計數(shù),就是用skb->users計數(shù)來計算共享的地方。
許多人理解了ptype_all和ptype_base鏈的作用之后,就認(rèn)為為什么不用下面的算法實現(xiàn)。
  1. for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) {
  2.     if (ptype->type == type && (!ptype->dev || ptype->dev == skb->dev)) {
  3.         atomic_inc(&skb->users);
  4.         ptype->func(skb, skb->dev, ptype);
  5.    }
  6. }
  7. kfree_skb(skb);
復(fù)制代碼

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

<三> 利用pt_prev來提高效率

    理解了上面的內(nèi)容之后,咱們來看看2.4中的代碼。
  1. for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) {
  2.     if (ptype->type == type && (!ptype->dev || ptype->dev == skb->dev)) {
  3.         if (pt_prev) {
  4.             if (!pt_prev->data)
  5.                deliver_to_old_ones(pt_prev, skb, 0);
  6.            else {
  7.                 /*到這里,那么pt_prev指針不為空,ptype(當(dāng)前的)不為空,那么肯定要共享一次了,所以加1*/
  8.                 atomic_inc(&skb->users);
  9.                 pt_prev->func(skb,skb->dev, pt_prev);
  10.                /*執(zhí)行上面的函數(shù)之后,會在里面減1。所以相對來說,上面兩句代碼執(zhí)行之后并沒有對skb->users的值進(jìn)行影響。*/
  11.           }
  12.        }
  13.        pt_prev = ptype;
  14. }
  15. }

  16. /*現(xiàn)在skb->users的計數(shù)還是為1*/
  17. if (pt_prev) {
  18.     if (!pt_prev->data)
  19.         deliver_to_old_ones(pt_prev, skb, 1);
  20.     else
  21.     /*在這里就沒有用atomic_inc(&skb->users);因為到這里,skb->users就為1,并且這里是最后一次,所以不用加1,
  22.        那么skb就直接在下面的pt_prev->func(skb, skb->dev,   pt_prev);函數(shù)中釋放了。
  23.    */
  24.     pt_prev->func(skb, skb->dev, pt_prev);
  25. } else{
  26.     /*到這里,已經(jīng)沒有對skb進(jìn)行操作的了。所以必須調(diào)用kfree_skb把skb釋放掉。*/
  27.     kfree_skb(skb);
  28. }
復(fù)制代碼

    你看,<二>和<三>相比是否少了一次調(diào)用kfree_skb呢。

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

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

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

論壇徽章:
0
6 [報告]
發(fā)表于 2014-06-14 15:10 |只看該作者
本帖最后由 huangbanban 于 2014-06-14 15:24 編輯

哈哈,我的理解是下面兩個函數(shù)出現(xiàn)的次數(shù)要一致,減少邏輯思維量
atomic_inc()
pt_prev->func()
而skb初始化中atomic_set(&skb->users, 1);就相當(dāng)于調(diào)用了一次atomic_inc()
不用再加多余的kfree_skb(),因為pt_prev->func()已經(jīng)包含了kfree_skb()

論壇徽章:
0
5 [報告]
發(fā)表于 2013-07-19 17:13 |只看該作者
+1回復(fù) 3# 賣萌犯法


   

論壇徽章:
0
4 [報告]
發(fā)表于 2013-06-24 00:02 |只看該作者
本帖最后由 honkiko 于 2013-06-24 00:06 編輯

回復(fù) 1# Godbach

頂。 解答了我很久以來一直存在的一個疑惑
   

論壇徽章:
0
3 [報告]
發(fā)表于 2013-06-21 10:44 |只看該作者
我認(rèn)為這個理解是不正確的。

首先我很懷疑linux內(nèi)核設(shè)計者是不是會為了節(jié)省一個atomic_dec_and_test,而破壞代碼的邏輯結(jié)構(gòu)。

我認(rèn)為:使用pt_prev是為了提升自定義packet_type的優(yōu)先級,使之位于某些特殊處理之前執(zhí)行,而內(nèi)核默認(rèn)的packet_type處理將位于這些特殊處理之后。

1.由于dev_add_pack的頭插方式,導(dǎo)致循環(huán)ptype_all和ptype_base結(jié)束之后,pt_prev將指向內(nèi)核默認(rèn)的packet_type,例如:對于ptype_all ,默認(rèn)是AF_PACKET;

2.在最后的pt_prev->fun(也就是內(nèi)核默認(rèn)處理)執(zhí)行之前,可以附加特殊操作,例如:2.4.21中的handle_diverter(netif_receive_skb,net\core\dev.c:1498),和2.6.34中的VLAN處理(netif_receive_skb,net\core\dev.c:2574);

3.由于添加特殊處理的位置位于for循環(huán)之后和最后pt_prev之前,導(dǎo)致內(nèi)核默認(rèn)的packet_type將位于這些處理之后執(zhí)行,而其他模塊自定義的packet_type將位于這些處理之前執(zhí)行(提升了優(yōu)先級);

4.所有packet_type處理的都是采取pt_prev的方式,可能就是為了給添加這些特殊處理留下空間。

至于最后一段缺少atomic_inc(&skb->users);的處理片段,只是追求額外福利罷了。

論壇徽章:
0
2 [報告]
發(fā)表于 2011-06-22 15:11 |只看該作者
回復(fù) 1# Godbach


有點不明白:
1)
kfree_skb中如果計數(shù)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);

}
當(dāng)引用數(shù)為1或者引用數(shù)減1等于零時, 回收包緩沖。

2)    結(jié)論:pt_prev使用的原因是為了減少一次kfree_skb的調(diào)用,提高效率。

不管有沒有pt_prev,最終都會調(diào)用__kfree_skb(skb)真正釋放內(nèi)存吧?那么結(jié)論中減少一次kfree_skb的調(diào)用是不是可以理解為 減少了一次引用計數(shù)減1的調(diào)用,這個應(yīng)該不怎么耗時吧?
  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP