《Linux核心設計與實現》讀書筆記(5)— 下半部和推後執行的工作(1)

來源:互聯網
上載者:User

下半部和推後執行的工作

1.下半部

    下半部的任務就是執行與中斷處理密切相關但中斷處理常式本身不執行的工作,對於在上半部和下半部之間劃分工作,儘管不存在某種嚴格的規則,但還是有一些提示可供借鑒:

    1)如果一個任務對時間非常敏感,將其放在中斷處理常式中執行。

    2)如果一個任務和硬體相關,將其放在中斷處理常式中執行。

    3)如果一個任務要保證不被其他中斷(特別是相同的中斷)打斷,將其放在中斷處理常式中執行。

    4)其他所有任務,考慮放置在下半部執行。

    我們希望盡量減少中斷處理常式中需要完成的工作量,因為在它啟動並執行時候當前的中斷線(或全域中斷)都會被屏蔽,而縮短中斷被屏蔽的時間對系統的響應能力和效能都至關重要。再加上中斷處理常式要與其他程式(甚至是其他中斷程式)非同步執行,所以要縮短中斷處理常式的執行,把一些工作交給下半部執行。

 

2.非強制中斷

    非強制中斷是在編譯期間靜態分配的,在kernel/softirq.c中定義了一個包含有32個softirq_action結構體的數組,因此最多隻能有32個非強制中斷。注意這是一個定值——註冊的非強制中斷數目的最大值沒法動態改變。在2.6核心中,這32個項中只用到了6個。

    非強制中斷處理常式action的函數原型為 void softirq_handler(struct softirq_action *),當核心運行一個非強制中斷處理常式的時候,它就會執行這個action函數,其唯一的參數為指向相應softirq_action結構體的指標,一個非強制中斷不會搶佔另外一個非強制中斷,唯一可以搶佔非強制中斷的是中斷處理常式。不過,其他的非強制中斷——甚至是相同類型的非強制中斷可以在其他處理器上執行。

    一個註冊的非強制中斷必須在被標記後才會執行。稱作觸發非強制中斷(raising the softirq)。通常,中斷處理常式會返回前標記它的非強制中斷,使其在稍後被執行。在下列地方,待處理的非強制中斷會被檢查和執行:

    1)從一個硬體中斷代碼處返回時。

    2)在ksoftirqd核心線程中。

    3)在那些顯式檢查的執行待處理的非強制中斷的代碼中,如網路子系統中。

    不管是用什麼方法喚起,非強制中斷都要在do_softirq()中執行。該函數很簡單,如果有待處理的非強制中斷,do_softirq()會迴圈遍曆每一個,調用它的處理常式。

u32 pending = softirq_pending(cpu);if( pending ){    struct softirq_action *h = softirq_vec;    softirq_pending( cpu ) = 0;    do {                if( pending & 1 )            h->action( h );        h++;        pending >>= 1;    }while( pending );}

    它檢查並執行所有待處理的非強制中斷,具體要做的包括:

    1)用局部變數pending儲存softirq_pending()宏的傳回值,它是待處理的非強制中斷的32位位元影像——如果第n位被設定為1,那麼第n位對應類型的非強制中斷等待處理。

    2)現在待處理的非強制中斷位元影像已經被儲存,可以將實際的非強制中斷位元影像清零了。

    3)將指標h指向softirq_vec的第一項。

    4)如果pending的第一位被置為1,h->action( h )被調用。

    5)指標加1,所以現在它指向softirq_vec數組的第二項。

    6)位元遮罩pending右移一位,這樣會丟棄原第一位,然後讓其他各位依次向右移動一個位置。於是,原來的第二位現在就在第一位的位置上(依次類推)。

    7)現在指標h指向數組的第二項,pending位元遮罩的第二位現在也到了第一位上。重複執行上面的步驟。

    8)一直重複下去,直到pending為0,這表明已經沒有待處理的非強制中斷了。

 

3.使用非強制中斷

    1)分配索引。在編譯期間,可以通過<linux/interrupt.h>中定義的一個枚舉類型來靜態地聲明非強制中斷。核心用從0開始的索引來表示一種相對優先順序。索引號小的非強制中斷在索引號大的非強制中斷之前執行。

    2)註冊處理常式。在運行時通過調用open_softirq()註冊非強制中斷處理常式,該函數有三個參數:非強制中斷的索引號,處理函數和data域存放的數值。

        open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);

        非強制中斷處理常式執行的時候,允許響應中斷,但它自己不能休眠。在一個處理常式啟動並執行時候,當前處理器上的非強制中斷被禁止,但其他的處理器仍可以執行別的非強制中斷(甚至是同    一類型的非強制中斷)。這意味著任何共用資料都需要嚴格的鎖保護。大部分非強制中斷處理常式都通過採取單一處理器資料(僅屬於某一個處理器的資料,因此根本不需要加鎖)或其他一些  技巧來避免顯式地加鎖,從而提供更出色的效能。

    3)觸發非強制中斷。raise_softirq()函數可以將一個非強制中斷設定為掛起狀態,讓它下次調用do_softirq()函數時投入運行。

        raise_softirq(NET_TX_SOFTIRQ);

        該函數在觸發一個非強制中斷之前先要禁止中斷,觸發後再恢複回原來的狀態。

        在中斷處理常式中觸發非強制中斷是最常見的形式。在這種情況下,中斷處理常式執行硬體裝置的相關操作,然後觸發相應的非強制中斷,最後退出。核心在執行完中斷處理常式以後,馬上就會調用do_softirq()函數,於是非強制中斷開始執行中斷處理常式留給它去完成的剩餘任務。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.