閱讀576 返回首頁    go 阿裏雲 go 技術社區[雲棲]


網絡子係統19_積壓設備

//	1.積壓設備的目的:
//		napi設備,非napi設備同一處理接口,linux為所有不使用napi的驅動程序,提供了一個虛擬設備,叫做積壓設備。
//	2.與積壓設備有關的數據結構:
//		2.1 每個cpu都有一個積壓設備,保存在softnet_data->backlog_dev
//		2.2 每個cpu都有一個積壓設備的輸入隊列,保存在softnet_data->input_pkt_queue,所有非napi設備的入口skb,均掛載到此隊列。
//		2.3 內核為積壓設備的提供poll函數,process_backlog

//	積壓設備的poll函數
//	調用路徑:net_rx_action->process_backlog
//	參數:
//		backlog_dev,積壓設備
//		budget,函數此次運行可以處理的skb配額

//	返回值:
//		<0 , 表明設備還有待處理的入口幀,此時設備仍然在poll_list中,且設備處於關中斷狀態
//		=0 , 表明設備已經處理完所有的入口幀,此時設備已經從poll_list中刪除,可接收重新調度,設備中斷已開啟
//	函數主要任務:
//		1.函數運行不能超過1個jiffies,處理的skb不能超過配額
//		2.在關中斷的情況下,從softnet->input_pkt_queue取下入口skb,後開中斷
//			2.1 如果有入口skb
//				2.1.1 通過netif_receive_skb向上層協議傳遞skb
//				2.1.2 遞減入口設備的引用計數
//			2.2 如果在運行時間不足1個jiffies,並且沒有超過配額的情況下,處理完了入口隊列的所有skb
//				2.2.1 更新設備的可用配額
//				2.2.2 由於已經沒有入口數據,因此將擠壓設備從調度隊列poll_list上取下來
//				2.2.3 清除積壓設備的調度標誌,表示設備可以接收下一次調度
//				2.2.4 如果之前入口隊列滿,被設置了throttle,則在入口隊列為空時,清除throttle

//	注:在入口隊列滿,設置了throttle,之後的入口數據都會被丟棄,直到入口隊列為空,清除throttle之後,才開始重新接收入口數據。
1.1 static int process_backlog(struct net_device *backlog_dev, int *budget)
{
	int work = 0;
	//此次調用可以處理的skb為 設備剩餘配額,傳入的配置中的較小者
	int quota = min(backlog_dev->quota, *budget);
	struct softnet_data *queue = &__get_cpu_var(softnet_data);
	unsigned long start_time = jiffies;

	for (;;) {
		struct sk_buff *skb;
		struct net_device *dev;

		//關閉本cpu中斷,因為input_pkt_queue可能會在中斷中被修改
		local_irq_disable();
		//從input_pkt_queue上退出一個skb
		skb = __skb_dequeue(&queue->input_pkt_queue);
		if (!skb)
			goto job_done;
		//開中斷
		local_irq_enable();

		dev = skb->dev;

		//將skb向上傳遞
		netif_receive_skb(skb);
		//遞減接收此skb的dev的引用計數
		dev_put(dev);
		//消費流量個數-1
		work++;
		//此函數運行時間應該 < 1 jiffies
		if (work >= quota || jiffies - start_time > 1)
			break;

	}
	//將設備的配額減去實際消費的流量個數
	backlog_dev->quota -= work;
	//將打算讓設備消費的流量個數中減去實際消費的流量個數
	*budget -= work;
	return -1;

//表示接收隊列為空
job_done:
	backlog_dev->quota -= work;
	*budget -= work;
	//將積壓設備從poll_list上刪除
	list_del(&backlog_dev->poll_list);
	smp_mb__before_clear_bit();
	//清除積壓設備__LINK_STATE_RX_SCHED標識,表示積壓設備重新可以接收調度
	netif_poll_enable(backlog_dev);

	//如果此cpu的輸入隊列已經關閉,開啟輸入隊列
	if (queue->throttle)
		queue->throttle = 0;
	//開本cpu中斷
	local_irq_enable();
	return 0;
}


//	對積壓設備的調度
//	調用路徑 : 非napi設備的接收中斷->netif_rx
2.1 int netif_rx(struct sk_buff *skb)
{
	...
	netif_rx_schedule(&queue->backlog_dev);
	...
}

最後更新:2017-04-03 15:22:09

  上一篇:go tomcat服務器的性能優化
  下一篇:go Com編程入門——什麼是COM,如何使用COM