17.7. 中斷處理

2018-02-24 15:50 更新

17.7.?中斷處理

大部分硬件接口通過(guò)一個(gè)中斷處理來(lái)控制. 硬件中斷處理器來(lái)發(fā)出 2 種可能的信號(hào): 一個(gè)新報(bào)文到了或者一個(gè)外出報(bào)文的發(fā)送完成了. 網(wǎng)絡(luò)接口也能夠產(chǎn)生中斷來(lái)指示錯(cuò)誤, 例如狀態(tài)改變, 等等.

通常的中斷過(guò)程能夠告知新報(bào)文到達(dá)中斷和發(fā)送完成通知的區(qū)別, 通過(guò)檢查物理設(shè)備中的狀態(tài)寄存器. snull 接口類似地工作, 但是它的狀態(tài)字在軟件中實(shí)現(xiàn), 位于 dev->priv. 網(wǎng)絡(luò)接口的中斷處理看來(lái)如此:


static void snull_regular_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
    int statusword;
    struct snull_priv *priv;
    struct snull_packet *pkt = NULL;
    /*

    *
    As usual, check the "device" pointer to be sure it is

    *
    really interrupting.

    *
    Then assign "struct device *dev"

    */
    struct net_device *dev = (struct net_device *)dev_id;
    /* ... and check with hw if it's really ours */

    /* paranoid */
    if (!dev)
        return;

    /* Lock the device */
    priv = netdev_priv(dev);
    spin_lock(&priv->lock);

    /* retrieve statusword: real netdevices use I/O instructions */
    statusword = priv->status;
    priv->status = 0;
    if (statusword & SNULL_RX_INTR) {

        /* send it to snull_rx for handling */
        pkt = priv->rx_queue;
        if (pkt) {

            priv->rx_queue = pkt->next;
            snull_rx(dev, pkt);

        }
    }
    if (statusword & SNULL_TX_INTR) {

        /* a transmission is over: free the skb */
        priv->stats.tx_packets++;
        priv->stats.tx_bytes += priv->tx_packetlen;
        dev_kfree_skb(priv->skb);

    }

    /* Unlock the device and we are done */
    spin_unlock(&priv->lock);
    if (pkt) snull_release_buffer(pkt); /* Do this outside the lock! */
    return;

}

中斷處理的第一個(gè)任務(wù)是取一個(gè)指向正確 net_device 結(jié)構(gòu)的指針. 這個(gè)指針通常來(lái)自作為參數(shù)收到的 dev_id 指針.

中斷處理的有趣部分處理"發(fā)送結(jié)束"的情況. 在這個(gè)情況下, 統(tǒng)計(jì)量被更新, 調(diào)用 dev_kfree_skb 來(lái)返回 socket 緩存給系統(tǒng). 實(shí)際上, 有這個(gè)函數(shù)的 3 個(gè)變體可以調(diào)用:

dev_kfree_skb(struct sk_buff *skb);
這個(gè)版本應(yīng)當(dāng)在你知道你的代碼不會(huì)在中斷上下文中運(yùn)行時(shí)調(diào)用. 因?yàn)?snull 沒(méi)有實(shí)際的硬件中斷, 我們使用這個(gè)版本.

dev_kfree_skb_irq(struct sk_buff *skb);
如果你知道會(huì)在中斷處理中釋放緩存, 使用這個(gè)版本, 它對(duì)這個(gè)情況做了優(yōu)化.

dev_kfree_skb_any(struct sk_buff *skb);
如果相關(guān)代碼可能在中斷或非中斷上下文運(yùn)行時(shí), 使用這個(gè)版本.

最后, 如果你的驅(qū)動(dòng)已暫時(shí)停止了發(fā)送隊(duì)列, 這常常是用 netif_wake_queue 重啟它的地方.

報(bào)文的接收, 相比于發(fā)送, 不需要特別的中斷處理. 調(diào)用 snull_rx (我們已經(jīng)見(jiàn)過(guò))就是全部所需.

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)