免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
linux內(nèi)核中的軟中斷的實(shí)現(xiàn)

  最近在閱讀linux內(nèi)核源碼,把自己的一些理解發(fā)上來,一方面看到的朋友可以幫我指正我理解偏差的地方,別一方面也算是做一個簡單的總結(jié)。

  首先調(diào)用open_softirq()函數(shù)來初始化軟件中斷處理函數(shù),將軟件中斷處理函數(shù)根據(jù)軟中斷的下標(biāo)號插入到softirq_vec數(shù)組中,實(shí)現(xiàn)過程很簡單如下:1 2 3 4 void open_softirq(int nr, void (*action)(struct softirq_action *)) { softirq_vec[nr].action = action; } softirq_vec數(shù)據(jù)有32個元素,對應(yīng)的是可以有32個軟件中斷,但實(shí)際上linux只是使用了其中的6個軟中斷,相應(yīng)的每一個CPU都會有一個對應(yīng)的32位的掩碼__softirq_pending描述掛起的軟中斷,每一位對應(yīng)一個軟件中斷,__soctirq_penging在irq_cpustat_t中定義,如下:@include/asm/hardirq.h 1 2 3 4 5 6 typedef struct { unsigned int __softirq_pending; unsigned long idle_timestamp; unsigned int __nmi_count; /* arch dependent */ unsigned int __irq_count; /* arch dependent */ } ____cacheline_aligned irq_cpustat_t;其中l(wèi)ocal_softirq_pending()宏用于選擇當(dāng)前CPU所對應(yīng)的__softirq_penging掩碼。相關(guān)的宏如下:@include/linux/irq_cpustat.h 1 2 3 4 #define local_softirq_pending() \ __IRQ_STAT(smp_processor_id() , __softirq_pending) #define __IRQ_STAT(cpu , member) (irq_stat[cpu].member)

  接著調(diào)用raise_softirq()函數(shù)來激活軟中斷,函數(shù)如下:@kernel/softirq.c 1 2 3 4 5 6 7 8 9 void raise_softirq(unsigned int nr) { unsigned long flags; /* 將eflags寄存器的IF標(biāo)志保存到flags,并且禁用了本地CPU上的中斷 */ local_irq_save(flags); raise_softirq_irqoff(nr); /* 根據(jù)flags變量的值恢復(fù)eflags寄存器的IF標(biāo)志,重新打開本地CPU上的中斷 */ local_irq_restore(flags); } raise_softirq_irqoff()函數(shù)必須是在禁止中斷的情況下執(zhí)行的,它首先調(diào)用__raise_softirq_irqoff()宏激活軟件中斷,其實(shí)也就是設(shè)置當(dāng)前CPU所對應(yīng)的__softirq_pending所對應(yīng)的軟中斷的位,以表示該軟中斷已激活。如果當(dāng)前正處于中斷或者軟中斷當(dāng)中,那么raise_softirq_irqoff執(zhí)行結(jié)束,否則的話就調(diào)用wakeup_softirqd()函數(shù)激活ksoftirqd/n內(nèi)核線程來處理軟中斷。

  @kernel/softirq.c 1 2 3 4 5 6 7 inline void raise_softirq_irqoff(unsigned int nr) { __raise_softirq_irqoff(nr); if (!in_interrupt()) wakeup_softirqd(); } __rarse_softirq_irqoff()宏在/include/linux/interput.h中定義:1 2 3 4 #defome __raise_softirq_irqoff(nr) \ do{ or_softirq_pending(1UL << (nr)); } while(0) #define or_softirq_pending(x) (local_softirq_pending() |= (x))

  其中l(wèi)ocal_softirq_pending()宏已經(jīng)在上面列出來了,我不太明白的是__raise_softirq_irqoff()這個宏為什么要放到一個循環(huán)里面,它也只是執(zhí)行了一次,不過linux既然這樣寫就一定有它的道理,慢慢再去研究吧。

  這樣軟中斷已經(jīng)激活,其處理函數(shù)已經(jīng)加入到了softirq_sec數(shù)組中,并且相應(yīng)的標(biāo)志位已經(jīng)合適地設(shè)置,系統(tǒng)會周期性地檢查已經(jīng)掛起的軟中斷,當(dāng)在local_softirq_pending()中的某個位檢測到掛起的軟中斷的時候,就會調(diào)用do_softirq()函數(shù)對軟中斷進(jìn)行處理。

  do_softirq()函數(shù)定義如下:@ kernel/softirq.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 asmlinkage void do_softirq(void) { __u32 pending; unsigned long flags; if (in_interrupt()) return; local_irq_save(flags); pending = local_softirq_pending(); if (pending) __do_softirq(); local_irq_restore(flags); }如果在中斷上下文中調(diào)用了do_softirq函數(shù)或者禁用了軟件中斷,那么in_interrupt函數(shù)返回1,這時候do_softirq()不做任何事情,否則,它會把eflags寄存器IF標(biāo)志保存在flags中并禁用中斷,然后將local_softirq_pending()的值保存在pending變量中,檢測pending的值,如果pending不為0,則表示pending的某一位被設(shè)置,當(dāng)前CPU就有對應(yīng)的掛起的軟中斷需要進(jìn)行處理,調(diào)用__do_softirq()對掛起的軟中斷進(jìn)行處理,處理完成之后再根據(jù)flags變量的值恢復(fù)eflags寄存器并打開中斷。

  接下來看__do_softirq()函數(shù):1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 asmlinkage void __do_softirq(void) { struct softirq_action *h; __u32 pending; int max_restart = MAX_SOFTIRQ_RESTART; int cpu; pending = local_softirq_pending(); /* 增加preempt_count字段中軟中斷計(jì)數(shù)器的值, * 以此來禁用軟中斷,因?yàn)檐浖袛嗟目裳舆t函數(shù) * 一般是在開中斷的情況下執(zhí)行的,這樣就可能在__do_softirq 執(zhí)行 * 的過程中有別一個__do_softirq的實(shí)例正在執(zhí)行 * ,這樣就會影響可延遲函數(shù)的串行化執(zhí)行*/ __local_bh_disable((unsigned long)__builtin_return_address(0)); restart: set_softirq_pending(0); local_irq_enable(); h = softirq_vec; do { if (pending & 1) { int prev_count = preempt_count(); /* 執(zhí)行軟件中斷處理函數(shù) */ h->action(h); if (unlikely(prev_count != preempt_count())) { printk(KERN_ERR "huh, entered softirq %td %p" "with preempt_count %08x," " exited with %08x?\n", h - softirq_vec, h->action, prev_count, preempt_count()); preempt_count() = prev_count; } } h++; pending >>= 1; } while (pending); /* 禁用本地軟中斷 */ local_irq_disable(); pending = local_softirq_pending(); if (pending && ——max_restart) goto restart; if (pending) wakeup_softirqd(); _local_bh_enable(); }內(nèi)核循環(huán)地檢測每一個pending的位,以處理當(dāng)前位掛機(jī)的軟件中斷,為了防止內(nèi)核在執(zhí)行__do_softirq()的過程中不停地有新的softirq產(chǎn)生,以導(dǎo)致內(nèi)核無暇顧及其它,__do_softirq()在循環(huán)檢測的時候設(shè)置了外層循環(huán)的最大次數(shù)為10次,對pending的每一位檢測10次之后如果pending的值仍不為0,則表示當(dāng)前CPU仍有未處理的掛起的軟件中斷,這時候__do_softirq不再對它進(jìn)行處理,而是喚醒內(nèi)核線程ksoftirqd/n對它進(jìn)行處理。

  在函數(shù)開始的時候,先將軟件中斷的位圖__softirq_pending保存在pending局部變量中,然后調(diào)用set_softirq_pending(0)以清空軟中斷位圖,從而允許新的軟中斷的到來。接著調(diào)用local_irq_enable()來激活軟中斷?!矩?zé)編:eric】

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
淺析Linux的軟中斷的實(shí)現(xiàn)
內(nèi)核隨記(一)——理解中斷(3)
中斷下半部分析_softirq
linux中斷源碼分析4/4--軟中斷
硬中斷和軟中斷
linux設(shè)備驅(qū)動歸納總結(jié)(六):3.中斷的上半部和下半部——tasklet
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服