在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

關于網卡的收發包硬件中斷

Linux愛好者 ? 來源:Linux愛好者 ? 作者:Linux愛好者 ? 2022-09-26 09:40 ? 次閱讀

中斷(IRQ),尤其是軟中斷(softirq)的重要使用場景之一是網絡收發包, 但并未唯一場景。本文整理 IRQ/softirq 的通用基礎,這些東西和網絡收發包沒有直接關系, 雖然整理本文的直接目的是為了更好地理解網絡收發包。

什么是中斷?

CPU 通過時分復用來處理很多任務,這其中包括一些硬件任務,例如磁盤讀寫、鍵盤輸入,也包括一些軟件任務,例如網絡包處理。在任意時刻,一個 CPU 只能處理一個任務。當某個硬件或軟件任務此刻沒有被執行,但它希望 CPU 來立即處理時,就會給 CPU 發送一個中斷請求 —— 希望 CPU 停下手頭的工作,優先服務“我”。中斷是以事件的方式通知 CPU 的,因此我們常看到 “XX 條件下會觸發 XX 中斷事件” 的表述。

兩種類型:

外部或硬件產生的中斷,例如鍵盤按鍵。

軟件產生的中斷,異常事件產生的中斷,例如除以零

管理中斷的設備:Advanced Programmable Interrupt Controller(APIC)。

硬中斷

中斷處理流程

中斷隨時可能發生,發生之后必須馬上得到處理。收到中斷事件后的處理流程:

搶占當前任務:內核必須暫停正在執行的進程;

執行中斷處理函數:找到對應的中斷處理函數,將 CPU 交給它(執行);

中斷處理完成之后:第 1 步被搶占的進程恢復執行。

Maskable and non-maskable

Maskable interrupts 在 x64_64 上可以用 sti/cli 兩個指令來屏蔽(關閉)和恢復:

staticinlinevoidnative_irq_disable(void){
asmvolatile("cli":::"memory");//清除IF標志位
}
staticinlinevoidnative_irq_enable(void){
asmvolatile("sti":::"memory");//設置IF標志位
}

在屏蔽期間,這種類型的中斷不會再觸發新的中斷事件。大部分 IRQ 都屬于這種類型。例子:網卡的收發包硬件中斷。

Non-maskable interrupts 不可屏蔽,所以在效果上屬于更緊急的類型。

問題:執行足夠快 vs 邏輯比較復雜

IRQ handler 的兩個特點:

執行要非常快,否則會導致事件(和數據)丟失;

需要做的事情可能非常多,邏輯很復雜,例如收包

這里就有了內在矛盾。

解決方式:延后中斷處理(deferred interrupt handling)

傳統上,解決這個內在矛盾的方式是將中斷處理分為兩部分:

top half

bottom half

這種方式稱為中斷的推遲處理或延后處理。以前這是唯一的推遲方式,但現在不是了。現在已經是個通用術語,泛指各種推遲執行中斷處理的方式。按這種方式,中斷會分為兩部分:

第一部分:只進行最重要、必須得在硬中斷上下文中執行的部分;剩下的處理作為第二部分,放入一個待處理隊列;

第二部分:一般是調度器根據輕重緩急來調度執行,不在硬中斷上下文中執行

Linux 中的三種推遲中斷(deferred interrupts):

softirq

tasklet

workqueue

后面會具體介紹。

軟中斷

軟中斷子系統

軟中斷是一個內核子系統:

1、每個 CPU 上會初始化一個 ksoftirqd 內核線程,負責處理各種類型的 softirq 中斷事件;

用 cgroup ls 或者 ps -ef 都能看到:

$systemd-cgls-k|grepsoftirq#-k:includekernelthreadsintheoutput
├─12[ksoftirqd/0]
├─19[ksoftirqd/1]
├─24[ksoftirqd/2]
...

2、軟中斷事件的 handler 提前注冊到 softirq 子系統, 注冊方式 open_softirq(softirq_id, handler)

例如,注冊網卡收發包(RX/TX)軟中斷處理函數:

//net/core/dev.c

open_softirq(NET_TX_SOFTIRQ,net_tx_action);
open_softirq(NET_RX_SOFTIRQ,net_rx_action);

3、軟中斷占 CPU 的總開銷:可以用 top 查看,里面 si 字段就是系統的軟中斷開銷(第三行倒數第二個指標):

$top-n1|head-n3
top-1805up86days,23:45,2users,loadaverage:5.01,5.56,6.26
Tasks:969total,2running,733sleeping,0stopped,2zombie
%Cpu(s):13.9us,3.2sy,0.0ni,82.7id,0.0wa,0.0hi,0.1si,0.0st

主處理

smpboot.c 類似于一個事件驅動的循環,里面會調度到 ksoftirqd 線程,執行 pending 的軟中斷。ksoftirqd 里面會進一步調用到 __do_softirq,

判斷哪些 softirq 需要處理,

執行 softirq handler

避免軟中斷占用過多 CPU

軟中斷方式的潛在影響:推遲執行部分(比如 softirq)可能會占用較長的時間,在這個時間段內, 用戶空間線程只能等待。反映在 top 里面,就是 si 占比。

不過 softirq 調度循環對此也有改進,通過 budget 機制來避免 softirq 占用過久的 CPU 時間。

unsignedlongend=jiffies+MAX_SOFTIRQ_TIME;
...
restart:
while((softirq_bit=ffs(pending))){
...
h->action(h);//這里面其實也有機制,避免softirq占用太多CPU
...
}
...
pending=local_softirq_pending();
if(pending){
if(time_before(jiffies,end)&&!need_resched()&&--max_restart)//避免softirq占用太多CPU
gotorestart;
}
...

硬中斷 -> 軟中斷 調用棧

前面提到,softirq 是一種推遲中斷處理機制,將 IRQ 的大部分處理邏輯推遲到了這里執行。兩條路徑都會執行到 softirq 主處理邏輯 __do_softirq(),

1、CPU 調度到 ksoftirqd 線程時,會執行到 __do_softirq();

2、每次 IRQ handler 退出時:do_IRQ() -> ...。

do_IRQ() 是內核中最主要的 IRQ 處理方式。它執行結束時,會調用 exiting_irq(),這會展開成 irq_exit()。后者會檢查是pending 的 softirq,有的話就喚醒:

//arch/x86/kernel/irq.c

if(!in_interrupt()&&local_softirq_pending())
invoke_softirq();

進而會使 CPU 執行到 __do_softirq()。

軟中斷觸發執行的步驟

To summarize, each softirq goes through the following stages: 每個軟中斷會經過下面幾個階段:

通過 open_softirq() 注冊軟中斷處理函數;

通過 raise_softirq() 將一個軟中斷標記為 deferred interrupt,這會喚醒改軟中斷(但還沒有開始處理);

內核調度器調度到 ksoftirqd 內核線程時,會將所有等待處理的 deferred interrupt(也就是 softirq)拿出來,執行對應的處理方法(softirq handler);

以收包軟中斷為例, IRQ handler 并不執行 NAPI,只是觸發它,在里面會執行到 raise NET_RX_SOFTIRQ;真正的執行在 softirq,里面會調用網卡的 poll() 方法收包。IRQ handler 中會調用 napi_schedule(),然后啟動 NAPI poll(),

這里需要注意,雖然 IRQ handler 做的事情非常少,但是接下來處理這個包的 softirq 和 IRQ 在同一個 CPU 運行。這就是說,如果大量的包都放到了同一個 RX queue,那雖然 IRQ 的開銷可能并不多,但這個 CPU 仍然會非常繁忙,都花在 softirq 上了。解決方式:RPS。它并不會降低延遲,只是將包重新分發:RXQ -> CPU。

三種推遲執行方式(softirq/tasklet/workqueue)

前面提到,Linux 中的三種推遲中斷執行的方式:

softirq

tasklet

workqueue

其中,

softirq 和 tasklet 依賴軟中斷子系統,運行在軟中斷上下文中

workqueue 不依賴軟中斷子系統,運行在進程上下文中

softirq

前面已經看到, Linux 在每個 CPU 上會創建一個 ksoftirqd 內核線程。

softirqs 是在 Linux 內核編譯時就確定好的,例外網絡收包對應的 NET_RX_SOFTIRQ 軟中斷。因此是一種靜態機制。如果想加一種新 softirq 類型,就需要修改并重新編譯內核。

內部組織

在內部是用一個數組(或稱向量)來管理的,每個軟中斷號對應一個 softirq handler。數組和注冊:

//kernel/softirq.c

//NR_SOFTIRQS是enumsoftirqtype的最大值,在5.10中是10,見下面
staticstructsoftirq_actionsoftirq_vec[NR_SOFTIRQS]__cacheline_aligned_in_smp;

voidopen_softirq(intnr,void(*action)(structsoftirq_action*)){
softirq_vec[nr].action=action;
}

5.10 中所有類型的 softirq:

//include/linux/interrupt.h

enum{
HI_SOFTIRQ=0,//tasklet
TIMER_SOFTIRQ,//timer
NET_TX_SOFTIRQ,//networking
NET_RX_SOFTIRQ,//networking
BLOCK_SOFTIRQ,//IO
IRQ_POLL_SOFTIRQ,
TASKLET_SOFTIRQ,//tasklet
SCHED_SOFTIRQ,//schedule
HRTIMER_SOFTIRQ,//timer
RCU_SOFTIRQ,//lock
NR_SOFTIRQS
};

也就是在 cat /proc/softirqs 看到的哪些。

$cat/proc/softirqs
CPU0CPU1...CPU46CPU47
HI:20...01
TIMER:443727467971...313696270110
NET_TX:5791965998...4228754840
NET_RX:287285262341...8110655244
BLOCK:2611564...268986463918
IRQ_POLL:00...00
TASKLET:98207...129122
SCHED:18544271124268...51548045332269
HRTIMER:1222468926...2549724272
RCU:1469356972856...59617375917455

觸發(喚醒)softirq

voidraise_softirq(unsignedintnr){
local_irq_save(flags);//關閉IRQ
raise_softirq_irqoff(nr);//喚醒ksoftirqd線程(但執行不在這里,在ksoftirqd線程中)
local_irq_restore(flags);//打開IRQ
}
if(!in_interrupt())
wakeup_softirqd();

staticvoidwakeup_softirqd(void){
structtask_struct*tsk=__this_cpu_read(ksoftirqd);

if(tsk&&tsk->state!=TASK_RUNNING)
wake_up_process(tsk);
}

以收包軟中斷為例, IRQ handler 并不執行 NAPI,只是觸發它,在里面會執行到 raise NET_RX_SOFTIRQ;真正的執行在 softirq,里面會調用網卡的 poll() 方法收包。IRQ handler 中會調用 napi_schedule(),然后啟動 NAPI poll()。

tasklet

如果對內核源碼有一定了解就會發現,softirq 用到的地方非常少,原因之一就是上面提到的,它是靜態編譯的, 靠內置的 ksoftirqd 線程來調度內置的那 9 種 softirq。如果想新加一種,就得修改并重新編譯內核, 所以開發成本非常高。

實際上,實現推遲執行的更常用方式 tasklet。它構建在 softirq 機制之上, 具體來說就是使用了上面提到的兩種 softirq:

HI_SOFTIRQ

TASKLET_SOFTIRQ

換句話說,tasklet 是可以在運行時(runtime)創建和初始化的 softirq

void__initsoftirq_init(void){
for_each_possible_cpu(cpu){
per_cpu(tasklet_vec,cpu).tail=&per_cpu(tasklet_vec,cpu).head;
per_cpu(tasklet_hi_vec,cpu).tail=&per_cpu(tasklet_hi_vec,cpu).head;
}

open_softirq(TASKLET_SOFTIRQ,tasklet_action);
open_softirq(HI_SOFTIRQ,tasklet_hi_action);
}

內核軟中斷子系統初始化了兩個 per-cpu 變量:

tasklet_vec:普通 tasklet,回調 tasklet_action()

tasklet_hi_vec:高優先級 tasklet,回調 tasklet_hi_action()

structtasklet_struct{
structtasklet_struct*next;
unsignedlongstate;
atomic_tcount;
void(*func)(unsignedlong);
unsignedlongdata;
};

tasklet 再執行針對 list 的循環:

staticvoidtasklet_action(structsoftirq_action*a)
{
local_irq_disable();
list=__this_cpu_read(tasklet_vec.head);
__this_cpu_write(tasklet_vec.head,NULL);
__this_cpu_write(tasklet_vec.tail,this_cpu_ptr(&tasklet_vec.head));
local_irq_enable();

while(list){
if(tasklet_trylock(t)){
t->func(t->data);
tasklet_unlock(t);
}
...
}
}

tasklet 在內核中的使用非常廣泛。不過,后面又出現了第三種方式:workqueue。

workqueue

這也是一種推遲執行機制,與 tasklet 有點類似,但也有很大不同。

tasklet 是運行在 softirq 上下文中;

workqueue 運行在內核進程上下文中;這意味著 wq 不能像 tasklet 那樣是原子的;

tasklet 永遠運行在指定 CPU,這是初始化時就確定了的;

workqueue 默認行為也是這樣,但是可以通過配置修改這種行為。

使用場景

// Documentation/core-api/workqueue.rst:

Therearemanycaseswhereanasynchronousprocessexecutioncontext
isneededandtheworkqueue(wq)APIisthemostcommonlyused
mechanismforsuchcases.

Whensuchanasynchronousexecutioncontextisneeded,aworkitem
describingwhichfunctiontoexecuteisputonaqueue.An
independentthreadservesastheasynchronousexecutioncontext.The
queueiscalledworkqueueandthethreadiscalledworker.

Whilethereareworkitemsontheworkqueuetheworkerexecutesthe
functionsassociatedwiththeworkitemsoneaftertheother.When
thereisnoworkitemleftontheworkqueuetheworkerbecomesidle.
Whenanewworkitemgetsqueued,theworkerbeginsexecutingagain.

簡單來說,workqueue 子系統提供了一個接口,通過這個接口可以創建內核線程來處理從其他地方 enqueue 過來的任務。這些內核線程就稱為 worker threads,內置的 per-cpu worker threads

$systemd-cgls-k|grepkworker
├─5[kworker/0:0H]
├─15[kworker/1:0H]
├─20[kworker/2:0H]
├─25[kworker/3:0H]

結構體

//include/linux/workqueue.h

structworker_pool{
spinlock_tlock;
intcpu;
intnode;
intid;
unsignedintflags;

structlist_headworklist;
intnr_workers;
...

structwork_struct{
atomic_long_tdata;
structlist_headentry;
work_func_tfunc;
structlockdep_maplockdep_map;
};

kworker 線程調度 workqueues,原理與 ksoftirqd 線程調度 softirqs 一樣。但是我們可以為 workqueue 創建新的線程,而 softirq 則不行。

審核編輯:彭靜
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • cpu
    cpu
    +關注

    關注

    68

    文章

    10863

    瀏覽量

    211781
  • 硬件
    +關注

    關注

    11

    文章

    3328

    瀏覽量

    66224
  • 函數
    +關注

    關注

    3

    文章

    4331

    瀏覽量

    62622

原文標題:Linux 中斷( IRQ / softirq )基礎:原理及內核實現

文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    硬件設計】直放站相關——發包

    硬件設計】直放站相關——發包發包。請有設計能力的朋友聯系我。要設計的產品大致是 在直放站的基礎上增加網絡控制功能。加我QQ:841445742
    發表于 03-23 15:17

    關于網卡硬件設計

    各位大蝦,小弟有現在在做一個冗余網卡的項目,硬件設計,我現在想用兩個網絡控制器和兩個網口,但是不知道怎么設計才能使得可以兩個網口切換(就是一個在工作,如果壞了,另一個馬上被切換),CPU不用設計,網絡控制器怎么與總線(PC104+)連接,各位高手,幫幫忙吧。。。
    發表于 11-24 11:05

    網卡驅動收發包過程 精選資料分享

    網卡網卡工作在物理層和數據鏈路層,主要由PHY/MAC芯片、Tx/Rx FIFO、DMA等組成,其中網線通過變壓器接PHY芯片、PHY芯片通過MII接MAC芯片、MAC芯片接PCI總線PHY芯片主要
    發表于 07-27 08:08

    請問網卡驅動收發包過程是怎樣的?

    請問網卡驅動收發包過程是怎樣的?
    發表于 10-09 08:58

    Windows環境下硬件中斷的性能分析

    分析了32 位 Windows 系統實現硬件中斷服務的內部機理和系統對中斷信號的響應性能,通過比較多種測試環境下得到的中斷延時,討論了中斷
    發表于 06-27 10:57 ?26次下載

    基于智能網卡的無中斷通信設計

    針對高速重載工作環境提出了一種主機和智能外設之間的無中斷通信方式并且在一塊集成CPU 的智能千兆位光纖網卡上實現了該通信方式主要從地址獲取緩沖區的訪問以及公用控制信息
    發表于 06-28 17:07 ?25次下載
    基于智能<b class='flag-5'>網卡</b>的無<b class='flag-5'>中斷</b>通信設計

    聯發科技linkIt?7687硬件發包

    聯發科技linkIt?7687硬件發包
    發表于 12-25 22:46 ?0次下載

    關于SYS BIOS的硬件中斷和空閑線程介紹

    SYS BIOS簡介-硬件中斷和空閑線程
    的頭像 發表于 08-20 00:35 ?4120次閱讀

    DPDK安裝教程和DPDK程序運行收發包示例程序及性能對比實驗的詳細概述

    本文檔的主要內容詳細介紹的是DPDK安裝教程和DPDK程序運行收發包示例程序及性能對比實驗的詳細概述。
    發表于 09-03 08:00 ?0次下載
    DPDK安裝教程和DPDK程序運行<b class='flag-5'>收發包</b>示例程序及性能對比實驗的詳細概述

    STM32的CAN收發數據死在硬件錯誤中斷

    STM32的CAN收發數據死在硬件錯誤中斷使用uCosIII的消息隊列,當CAN接收到數據,使用消息隊列給CAN數據處理任務發送一個消息CAN數據處理任務使用請求消息函數收到一個消息,進行下一步操作
    發表于 12-09 09:36 ?22次下載
    STM32的CAN<b class='flag-5'>收發</b>數據死在<b class='flag-5'>硬件</b>錯誤<b class='flag-5'>中斷</b>

    STM32 CubeMx(三)外部中斷和串口收發

    本篇博客講解了外部中斷中斷概念,阻塞式串口收發,串口通信概念,中斷式串口收發,DMA串口收發
    發表于 01-12 20:22 ?1次下載
    STM32 CubeMx(三)外部<b class='flag-5'>中斷</b>和串口<b class='flag-5'>收發</b>

    硬件中斷OB的功能

    硬件中斷 OB 在發生相關硬件事件時執行,可以快速的響應并執行硬件中斷 OB 中的程序(例如立即停止某些關鍵設備)。
    的頭像 發表于 02-12 11:44 ?2527次閱讀

    軟件中斷硬件中斷的區別

    的理論知識。 硬件中斷硬件中斷是由某些硬件設備引起的,例如啟動 I/O 的請求、硬件故障或類
    的頭像 發表于 11-07 16:52 ?1084次閱讀
    軟件<b class='flag-5'>中斷</b>與<b class='flag-5'>硬件</b><b class='flag-5'>中斷</b>的區別

    中斷與硬中斷介紹

    ? 硬中斷是由外部事件引起的因此具有隨機性和突發性;硬中斷是否可以嵌套的,是否有優先級(由硬件設計體系決定)。 ? 軟中斷是執行中斷指令產生
    的頭像 發表于 11-07 17:02 ?880次閱讀

    網卡硬件故障及解決方法

    網卡硬件故障及解決方法 網卡是計算機與網絡之間進行通信的重要組件之一。然而,由于各種原因,網卡硬件故障可能會導致計算機無法連接到網絡或者網絡
    的頭像 發表于 12-27 15:17 ?3654次閱讀
    主站蜘蛛池模板: 一级毛片免费在线观看网站| 伊人久久影院大香线蕉| 91免费在线视频| www.99在线| 97综合视频| 天天射天天草| 久久免费国产| 欧美黑人性受xxxx喷水| 在线观看日本亚洲一区| 最新久久免费视频| 五月开心六月伊人色婷婷| 色图视频| 久久婷婷是五月综合色狠狠| 国产三及| 天天干视频网| 777欧美午夜精品影院| 午夜国产精品久久久久| 亚洲色图图片区| 欧美午夜性| 国产三a级日本三级日产三级| 九草伊人| 成年美女黄网站色大免费视频| 亚洲一区二区三区四区五区六区| 中文天堂在线观看| 久久99久久精品免费思思6| 午夜视频在线免费观看| 国产精品久久1024| 男男小说高h| 色偷偷97| 天天狠天天透| 中国成熟xxx视频| 成人a毛片免费全部播放| 免费黄色三级网站| 在线观看视频一区二区三区| 欧美一区二区三区精品| www.淫| 中文字幕在线二区| 五月婷婷综合色| 国模精品| 国产午夜免费视频片夜色| 成人aaa|