網絡子係統20_傳輸接收軟中斷
// 數據幀接收軟中斷處理函數 // 調用路徑:do_softirq->net_rx_action // 函數主要任務: // 1.在關中斷情況下檢查調度隊列poll_list是否有設備接收到入口幀,然後開中斷 // 2.單次運行處理的入口幀不能超過netdev_max_backlog=300,運行時間不能超過1個jiffies // 3.依次遍曆調度隊列poll_list // 4.如果設備配額以用完,或者設備驅動的poll函數表明仍然有入口數據幀 // 4.1 將設備重新添加poll_list尾部,重新分配配額,準備接受下一次調度 // 5.如果單次運行沒有調度完所有接收到入口幀的設備,則再次設置接受軟中斷調度標誌,退出 // 注:接收軟中斷中,poll_list上掛載的npai設備,或者非napi設備使用的積壓設備。 3.2 static void net_rx_action(struct softirq_action *h) { struct softnet_data *queue = &__get_cpu_var(softnet_data); unsigned long start_time = jiffies; int budget = netdev_max_backlog; //關本地中斷 local_irq_disable(); //有設備有輸入流量 while (!list_empty(&queue->poll_list)) { struct net_device *dev; //執行時間超過了一個1 jiffies //或者本次軟中斷處理的輸入流量已經超過了netdev_max_backlog,退出軟中 if (budget <= 0 || jiffies - start_time > 1) goto softnet_break; local_irq_enable(); //獲得設備指針 dev = list_entry(queue->poll_list.next, struct net_device, poll_list); //如果設備的配額已經用完,或者執行一次poll之後,此設備依然有待處理的流量 if (dev->quota <= 0 || dev->poll(dev, &budget)) { local_irq_disable(); //將設備從list上刪除,添加到list尾部 list_del(&dev->poll_list); list_add_tail(&dev->poll_list, &queue->poll_list); //給設備重新分配配額,已weight作為一次分配的量,範圍從1024~64 if (dev->quota < 0) dev->quota += dev->weight; else dev->quota = dev->weight; } else { dev_put(dev); local_irq_disable(); } } out: local_irq_enable(); return; softnet_break: __get_cpu_var(netdev_rx_stat).time_squeeze++; //重新調度接收軟中斷 __raise_softirq_irqoff(NET_RX_SOFTIRQ); goto out; } // 發送軟中斷處理函數 // 一次處理output_queue中所有等待傳輸的設備 // 調用路徑:do_softirq->net_tx_action // 函數主要功能: // 1.釋放本cpu所有已經完成傳輸的skb // 2.關中斷的情況獲取本cpu的傳輸設備隊列output_queue, 其中的設備有數據需要進行傳輸 // 3.清除設備傳輸調度標誌,表明設備可以接收下一次傳輸調度 // 4.獲取設備隊列鎖queue_lock,通過隊列規則接口,進行設備數據傳輸 // 5.如果獲取queue_lock失敗,說明設備當前正在進行傳輸,重調度設備 // 注:發送軟中斷中,output_queue掛載的設備均為有隊列規則設備,沒有隊列規則的設備不會在軟中斷進行傳輸,因為其沒有傳輸調度的概念 3.3 static void net_tx_action(struct softirq_action *h) { struct softnet_data *sd = &__get_cpu_var(softnet_data); //如果完成隊列非空 if (sd->completion_queue) { struct sk_buff *clist; //關本cpu中斷 local_irq_disable(); //取下本cpu的完成隊列 clist = sd->completion_queue; sd->completion_queue = NULL; local_irq_enable(); while (clist) { struct sk_buff *skb = clist; clist = clist->next; //釋放對應的skb __kfree_skb(skb); } } //如果輸出隊列非空 if (sd->output_queue) { struct net_device *head; //將輸出隊列取下 local_irq_disable(); head = sd->output_queue; sd->output_queue = NULL; local_irq_enable(); while (head) { struct net_device *dev = head; //net_device 通過next_sched鏈接到output_queue上 head = head->next_sched; //一個內存屏障 smp_mb__before_clear_bit(); //設備準備好進行傳輸,清除設備調度標誌,說明,當設備執行傳輸時,屬於非調度狀態,可以被重新調度。 clear_bit(__LINK_STATE_SCHED, &dev->state); //獲取設備的輸出隊列鎖 if (spin_trylock(&dev->queue_lock)) { //通過出口隊列規則,調度設備 qdisc_run(dev); spin_unlock(&dev->queue_lock); } else { //說明隊列正在進行傳輸,重新調度設備 netif_schedule(dev); } } } }
最後更新:2017-04-03 15:22:11
上一篇:
更改 SAR 時間輸出格式 AM/PM
下一篇:
網絡子係統18_arp對代理的處理
matlab產生萊斯分布隨機數
Sql Server 常用函數
Project has no default.properties file! Edit the project properties to set one.錯誤解決方法
c# 數據類型與運算符
負載均衡(SLB)使用最佳實踐
??????????????????????????????Oracle Sharding????????????????????????-??????-????????????-?????????
使用Qt做一個簡易音樂播放器[Phonon淺談--續]
重磅!支付寶小程序悄然上線,分享能力更強大!ofo小程序怒懟摩拜小程序
四大經過市場驗證正確的手機思路
JavaEE中使用Filter來實現圖片的防盜鏈