亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 操作系統 > 正文

內核源碼分析之軟中斷(基于3.16-rc4)

2024-06-28 13:25:06
字體:
來源:轉載
供稿:網友
內核源碼分析之軟中斷(基于3.16-rc4)

1.和軟中斷相關的數據結構:

softing_vec數組(kernel/softirq.c)

1 static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;

NR_SOFTIRQS值為10,說明內核支持10個軟中斷函數。

softirq_action結構體(include/linux/interrupt.h)

1 struct softirq_action2 {3     void    (*action)(struct softirq_action *);4 };

action是函數指針變量,指向了某個軟中斷函數。

irq_cpustat_t結構體(arch/x86/include/asm/hardirq.h)

 1 typedef struct { 2     unsigned int __softirq_pending; 3     unsigned int __nmi_count;    /* arch dependent */ 4 #ifdef CONFIG_X86_LOCAL_APIC 5     unsigned int apic_timer_irqs;    /* arch dependent */ 6     unsigned int irq_spurious_count; 7     unsigned int icr_read_retry_count; 8 #endif 9 #ifdef CONFIG_HAVE_KVM10     unsigned int kvm_posted_intr_ipis;11 #endif12     unsigned int x86_platform_ipis;    /* arch dependent */13     unsigned int apic_perf_irqs;14     unsigned int apic_irq_work_irqs;15 #ifdef CONFIG_SMP16     unsigned int irq_resched_count;17     unsigned int irq_call_count;18     /*19      * irq_tlb_count is double-counted in irq_call_count, so it must be20      * subtracted from irq_call_count when displaying irq_call_count21      */22     unsigned int irq_tlb_count;23 #endif24 #ifdef CONFIG_X86_THERMAL_VECTOR25     unsigned int irq_thermal_count;26 #endif27 #ifdef CONFIG_X86_MCE_THRESHOLD28     unsigned int irq_threshold_count;29 #endif30 #if IS_ENABLED(CONFIG_HYPERV) || defined(CONFIG_XEN)31     unsigned int irq_hv_callback_count;32 #endif33 } ____cacheline_aligned irq_cpustat_t;

每個cpu都有一個這樣的結構體變量,在軟中斷中,我們要使用的是第2行的成員,32位的軟中斷掩碼。當有一個軟中斷被掛起(將要被執行)的時候,會設置該掩碼中的相應位。

2.軟中斷的執行過程

首先使用open_softirq()函數注冊軟中斷函數,代碼如下(kernel/softirq.c):

1 void open_softirq(int nr, void (*action)(struct softirq_action *))2 {3     softirq_vec[nr].action = action;4 }

將軟中斷函數指針action存入softirq_vec數組的對應元素中。

接著,使用raise_softirq()激活軟中斷,代碼如下(kernel/softirq.c):

1 void raise_softirq(unsigned int nr)2 {3     unsigned long flags;4 5     local_irq_save(flags);6     raise_softirq_irqoff(nr);7     local_irq_restore(flags);8 }

第5行關閉本地中斷,第7行恢復中斷。第6行激活nr所對應的軟中斷函數。接著分析 raise_softirq_irqoff(),代碼如下(kernel/softirq.c):

 1 inline void raise_softirq_irqoff(unsigned int nr) 2 { 3     __raise_softirq_irqoff(nr); 4  5     /* 6      * If we're in an interrupt or softirq, we're done 7      * (this also catches softirq-disabled code). We will 8      * actually run the softirq once we return from 9      * the irq or softirq.10      *11      * Otherwise we wake up ksoftirqd to make sure we12      * schedule the softirq soon.13      */14     if (!in_interrupt())15         wakeup_softirqd();16 }

第3行__raise_softirq_irqoff函數設置了軟中斷掩碼的相應位,代碼如下(kernel/softirq.c)。然后第14行判斷軟中斷是否已經激活或者被禁用,如果沒有,那么在15行激活內核線程ksoftirq,去執行軟中斷。

1 void (unsigned int nr)2 {3     trace_softirq_raise(nr);4     or_softirq_pending(1UL << nr);5 }

具體而言,在第4行的函數中設置掩碼位。

3.下面分析下在哪些地方都可以進入軟中斷。

第一個地方,當然就是上邊所提到的,內核線程ksoftirq被激活的時候。下面看看ksoftirq線程(kernel/softirq.c)。

1 DEFINE_PER_CPU(struct task_struct *, ksoftirqd);

給每個cpu都定義一個指向struct task_struct類型的結構體變量,很顯然,該變量存的是ksoftirq線程的進程描述符。(由此也說明,linux的線程和進程是一個東西)

接著,我們要看看ksoftirq線程要執行的函數(kernel/softirq.c)。

 1 static void run_ksoftirqd(unsigned int cpu) 2 { 3     local_irq_disable(); 4     if (local_softirq_pending()) { 5         /* 6          * We can safely run softirq on inline stack, as we are not deep 7          * in the task stack here. 8          */ 9         __do_softirq();10         rcu_note_context_switch(cpu);11         local_irq_enable();12         cond_resched();13         return;14     }15     local_irq_enable();16 }

該函數就是ksoftirq線程的線程體。第9行__do_softirq()中調用所有軟中斷函數。

我們回過頭來再分析下wakeup_softirqd(),看看ksoftirq線程怎樣被喚醒(kernel/softirq.c)。

1 static void wakeup_softirqd(void)2 {3     /* Interrupts are disabled: no need to stop PReemption */4     struct task_struct *tsk = __this_cpu_read(ksoftirqd);5 6     if (tsk && tsk->state != TASK_RUNNING)7         wake_up_process(tsk);8 }

第4行把本地cpu的ksoftirq線程的描述符讀到tsk變量中,第6行中判斷ksoftirq線程如果沒有運行的話,第7行喚醒該線程。

第二個地方,中斷處理程序do_IRQ完成處理或者調用irq_exit函數時。下面看看irq_exit代碼(kernel/softirq.c)。

 1 void irq_exit(void) 2 { 3 #ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED 4     local_irq_disable(); 5 #else 6     WARN_ON_ONCE(!irqs_disabled()); 7 #endif 8  9     account_irq_exit_time(current);10     preempt_count_sub(HARDIRQ_OFFSET);11     if (!in_interrupt() && local_softirq_pending())12         invoke_softirq();13 14     tick_irq_exit();15     rcu_irq_exit();16     trace_hardirq_exit(); /* must be last! */17 }

不用我說了吧,我覺得你一眼就能瞄見了第12行??聪耰nvoke_softirq函數(kernel/softirq.c)。

 1 static inline void invoke_softirq(void) 2 { 3     if (!force_irqthreads) { 4 #ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK 5         /* 6          * We can safely execute softirq on the current stack if 7          * it is the irq stack, because it should be near empty 8          * at this stage. 9          */10         __do_softirq();11 #else12         /*13          * Otherwise, irq_exit() is called on the task stack that can14          * be potentially deep already. So call softirq in its own stack15          * to prevent from any overrun.16          */17         do_softirq_own_stack();18 #endif19     } else {20         wakeup_softirqd();21     }22 }

第3行force_irqthreads值為0,所以該函數也調用了__do_softirq()來執行軟中斷。

還有幾處地方暫時不分析了,以后有空補上。

4.下面來看下__do_softirq()函數(kernel/softirq.c)。

 1 asmlinkage __visible void __do_softirq(void) 2 { 3     unsigned long end = jiffies + MAX_SOFTIRQ_TIME; 4     unsigned long old_flags = current->flags; 5     int max_restart = MAX_SOFTIRQ_RESTART; 6     struct softirq_action *h; 7     bool in_hardirq; 8     __u32 pending; 9     int softirq_bit;10 11     /*12      * Mask out PF_MEMALLOC s current task context is borrowed for the13      * softirq. A softirq handled such as network RX might set PF_MEMALLOC14      * again if the socket is related to swap15      */16     current->flags &= ~PF_MEMALLOC;17 18     pending = local_softirq_pending();19     account_irq_enter_time(current);20 21     __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);22     in_hardirq = lockdep_softirq_start();23 24 restart:25     /* Reset the pending bitmask before enabling irqs */26     set_softirq_pending(0);27 28     local_irq_enable();29 30     h = softirq_vec;31 32     while ((softirq_bit = ffs(pending))) {33         unsigned int vec_nr;34         int prev_count;35 36         h += softirq_bit - 1;37 38         vec_nr = h - softirq_vec;39         prev_count = preempt_count();40 41         kstat_incr_softirqs_this_cpu(vec_nr);42 43         trace_softirq_entry(vec_nr);44         h->action(h);45         trace_softirq_exit(vec_nr);46         if (unlikely(prev_count != preempt_count())) {47             pr_err("huh, entered softirq %u %s %p with preempt_count %08x, exited with %08x?/n",48                    vec_nr, softirq_to_name[vec_nr], h->action,49                    prev_count, preempt_count());50             preempt_count_set(prev_count);51         }52         h++;53         pending >>= softirq_bit;54     }55 56     rcu_bh_qs(smp_processor_id());57     local_irq_disable();58 59     pending = local_softirq_pending();60     if (pending) {61         if (time_before(jiffies, end) && !need_resched() &&62             --max_restart)63             goto restart;64 65         wakeup_softirqd();66     }67 68     lockdep_softirq_end(in_hardirq);69     account_irq_exit_time(current);70     __local_bh_enable(SOFTIRQ_OFFSET);71     WARN_ON_ONCE(in_interrupt());72     tsk_restore_flags(current, old_flags, PF_MEMALLOC);73 } 

在該函數中循環調用的所有的被激活的軟中斷函數。第5行MAX_SOFTIRQ_RESTART值為10,表示最多循環10次(不能讓其他進程等太久),第32行獲取pending表中第一被設置的比特位,第44行開始執行設置過的軟中斷函數。第53行對pending進行右移運算,然后進入下次循環。直到將本輪所有已設置的軟中斷函數全部執行完,退出循環。第59行重新獲得本地cpu的軟中斷掩碼,第61行如果時間沒有超出end而且沒有出現更高優先級的進程并且10次尋環未用完,那么跳回restart,重新for循環。否則,第65行喚醒softirqd內核線程。然后退出本函數。

至此,軟中斷的處理過程就分析完了。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧洲亚洲在线视频| 国产成人精品网站| 亚洲欧洲一区二区三区在线观看| 久热精品在线视频| 大荫蒂欧美视频另类xxxx| 日韩久久免费视频| 少妇高潮久久久久久潘金莲| 一本一道久久a久久精品逆3p| 国产精品久久久久久久久| www欧美日韩| 欧美一级片久久久久久久| 亚洲一区精品电影| 91久久久久久久久| 欧美尺度大的性做爰视频| 57pao成人永久免费视频| 欧美孕妇孕交黑巨大网站| 欧美一级免费视频| 欧美专区国产专区| 久久久91精品国产一区不卡| 亚洲国产成人爱av在线播放| 亚洲自拍偷拍视频| 亚洲男人天堂手机在线| 久久视频这里只有精品| 日韩在线欧美在线国产在线| 成人黄色免费片| 色综合天天综合网国产成人网| 在线午夜精品自拍| 精品无码久久久久久国产| 欧美在线视频一二三| 成人444kkkk在线观看| 一区二区欧美日韩视频| 国产美女高潮久久白浆| 亚洲va欧美va国产综合剧情| 午夜精品一区二区三区在线播放| 亚洲欧美国产一本综合首页| 欧美大学生性色视频| 日韩av电影手机在线观看| 欧美日韩一区免费| 国产精品99久久99久久久二8| 国产91精品久久久久久| 色香阁99久久精品久久久| 欧美电影免费在线观看| 九九视频直播综合网| 欧美尤物巨大精品爽| 色综合久久久久久中文网| 久久久综合免费视频| 日韩成人av在线播放| 久久久久久有精品国产| 国产精品午夜一区二区欲梦| 欧美高清第一页| 欧美性做爰毛片| 日韩黄色在线免费观看| 高清欧美一区二区三区| 亚洲国内精品视频| 在线看日韩欧美| 欧美在线观看www| 色青青草原桃花久久综合| 欧美电影在线观看高清| 亚洲激情视频在线观看| 成人性教育视频在线观看| 亚洲一区二区日本| 欧美日韩国产精品一区| 成人免费网站在线| 97国产一区二区精品久久呦| 国产在线观看一区二区三区| 日韩av在线一区二区| 精品亚洲一区二区| 亚洲成av人影院在线观看| 一本一道久久a久久精品逆3p| 亚洲天堂av高清| 日韩免费在线免费观看| 国产日韩欧美在线看| 97久久伊人激情网| 26uuu久久噜噜噜噜| 日韩精品中文字幕在线| 成人久久18免费网站图片| 色综合老司机第九色激情| 俺也去精品视频在线观看| 国产成人亚洲综合91精品| 有码中文亚洲精品| 色综合久久精品亚洲国产| 粉嫩老牛aⅴ一区二区三区| 日韩av免费在线播放| 成人黄色片在线| 欧美成人午夜视频| 欧美日韩中文字幕日韩欧美| 91极品视频在线| 亚洲小视频在线| 欧美激情性做爰免费视频| 韩国国内大量揄拍精品视频| 中文字幕一精品亚洲无线一区| 91在线播放国产| 国产精品偷伦免费视频观看的| 国产不卡av在线| 欧美专区国产专区| 在线精品播放av| 欧美综合第一页| 久久久久久成人| 中文字幕亚洲综合久久筱田步美| 久久久av一区| 精品日本美女福利在线观看| 91精品国产电影| 欧美在线视频一区| 国产精品久久久久久亚洲影视| 日韩大片在线观看视频| 91九色单男在线观看| 国产女人精品视频| 欧美性一区二区三区| 成人免费直播live| 国产又爽又黄的激情精品视频| 欧美激情一二三| 最新国产精品亚洲| 亚洲一区999| 成人免费在线网址| 日本精品va在线观看| 成人性生交大片免费看小说| 亚洲欧美日韩另类| 欧美大片在线看免费观看| 国产精品一区二区三区久久久| 久久免费视频在线| 国产在线拍揄自揄视频不卡99| 美女啪啪无遮挡免费久久网站| 国产一区二区av| 91老司机精品视频| 国产精品久久久久久久久| 久久久视频精品| 亚洲国产成人91精品| 日韩福利在线播放| 日韩中文字幕在线免费观看| 国产在线观看精品一区二区三区| 亚洲精品美女久久久久| 成人xxxxx| 精品国内产的精品视频在线观看| 欧美在线观看日本一区| 国产精品第8页| 91免费综合在线| 欧美高跟鞋交xxxxhd| 成人做爰www免费看视频网站| 亚洲欧洲激情在线| 国外成人在线播放| 国产a级全部精品| 国产成人在线一区二区| 亚洲国产精品悠悠久久琪琪| 欧美在线免费看| 91精品视频在线| 成人免费福利视频| 欧美成人免费一级人片100| 性欧美xxxx交| 久久99久久亚洲国产| 国产成人激情小视频| 国产精品极品美女在线观看免费| 欧美电影在线观看高清| 久久久久99精品久久久久| 亚洲一区二区国产| 亚洲无亚洲人成网站77777| 91精品国产综合久久久久久久久| 亚洲免费中文字幕| 国产成人aa精品一区在线播放| 欧美日韩在线观看视频小说| 黑人精品xxx一区一二区| 欧美在线性爱视频| 欧美在线一区二区三区四| 九九精品在线播放| 欧美亚洲视频在线观看|