網絡子係統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來實現圖片的防盜鏈