已阅读5页,还剩7页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、软中断软中断的原理就略过了,讲内核的书上都有,此处省略1500字。1.1 注册还是以我最熟悉的两个老朋友做为开篇: open_softirq(NET_TX_SOFTIRQ, net_tx_action); open_softirq(NET_RX_SOFTIRQ, net_rx_action);open_softirq向内核注册一个软中断,其实质是设置软中断向量表相应槽位,注册其处理函数:1. void open_softirq(int nr, void (*action)(struct softirq_action *)2. 3. softirq_vecnr.action = action;4. 复制代码softirq_vec是整个软中断的向量表:1. struct softirq_action2. 3. void (*action)(struct softirq_action *);4. ;5.6. static struct softirq_action softirq_vecNR_SOFTIRQS _cacheline_aligned_in_smp;复制代码NR_SOFTIRQS是最大软中断向量数,内核支持的所有软中断如下:1. enum2. 3. HI_SOFTIRQ=0,4. TIMER_SOFTIRQ,5. NET_TX_SOFTIRQ,6. NET_RX_SOFTIRQ,7. BLOCK_SOFTIRQ,8. TASKLET_SOFTIRQ,9. SCHED_SOFTIRQ,10. HRTIMER_SOFTIRQ,11. RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */12.13. NR_SOFTIRQS14. ;复制代码好像后为为RPS新增了一个,不过这我的内核版本偏低。1.2 激活当需要调用软中断时,需要调用raise_softirq函数激活软中断,这里使用术语“激活”而非“调用”,是因为在很多情况下不能直接调用软中断。所以只能快速地将其标志为“可执行”,等待未来某一时刻调用。为什么“在很多情况下不能直接调用软中断”?试想一下下半部引入的理念,就是为了让上半部更快地执行。如果在中断程序代码中直接调用软中断函数,那么就失去了上半部与下半部的区别,也就是失去了其存在的意义。内核使用一个名为_softirq_pending的位图来描述软中断,每一个位对应一个软中断,位图包含在结构irq_stat中:1. typedef struct 2. unsigned int _softirq_pending;3. 4. _cacheline_aligned irq_cpustat_t;5.6. DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);复制代码宏or_softirq_pending用于设置相应的位(位或操作):1. #define or_softirq_pending(x) percpu_or(irq_stat._softirq_pending, (x)复制代码local_softirq_pending用于取得整个位图(而非某一位):1. #define local_softirq_pending() percpu_read(irq_stat._softirq_pending)复制代码宏_raise_softirq_irqoff是or_softirq_pending的包裹:1. #define _raise_softirq_irqoff(nr) do or_softirq_pending(1UL (nr); while (0)复制代码raise_softirq_irqoff通过调用_raise_softirq_irqoff实现激活软中断,它的参数nr即位软中断对应的位图槽位:1. /*2. * This function must run with irqs disabled!3. */4. inline void raise_softirq_irqoff(unsigned int nr)5. 6. /置位图,即标记为可执行状态7. _raise_softirq_irqoff(nr);8.9. /*10. * If were in an interrupt or softirq, were done11. * (this also catches softirq-disabled code). We will12. * actually run the softirq once we return from13. * the irq or softirq.14. *15. * Otherwise we wake up ksoftirqd to make sure we16. * schedule the softirq soon.17. */18. /设置了位图后,可以判断是否已经没有在中断上下文中了,如果没有,则是一个立即调用软中断的好时机。19. /in_interrupt另一个作用是判断软中断是否被禁用。20. /wakeup_softirqd唤醒软中断的守护进程ksoftirq。21. if (!in_interrupt()22. wakeup_softirqd();23. 复制代码现在可以来看激活软中断的所有含义了,raise_softirq函数完成这一操作:1. void raise_softirq(unsigned int nr)2. 3. unsigned long flags;4.5. /所有操作,应该关闭中断,避免嵌套调用6. local_irq_save(flags);7. raise_softirq_irqoff(nr);8. local_irq_restore(flags);9. 复制代码可见,激活的操作,主要是两点:、最重要的,就是置相应的位图,等待将来被处理;、如果此时已经没有在中断上下文中,则立即调用(其实是内核线程的唤醒操作),现在就是将来;2、调度时机是的,除了raise_softirq在,可能会(嗯,重要的是“可能”)通过wakeup_softirqd唤醒ksoftirqd外,还得明白软中断的其它调用时机。A、当do_IRQ完成了I/O中断时调用irq_exit:1. #ifdef _ARCH_IRQ_EXIT_IRQS_DISABLED2. # define invoke_softirq() _do_softirq()3. #else4. # define invoke_softirq() do_softirq()5. #endif6.7. void irq_exit(void)8. 9. account_system_vtime(current);10. trace_hardirq_exit();11. sub_preempt_count(IRQ_EXIT_OFFSET);12. if (!in_interrupt() & local_softirq_pending()13. invoke_softirq(); /调用软中断复制代码B、如果系统使用I/O APIC,在处理完本地时钟中断时:1. void _irq_entry smp_apic_timer_interrupt(struct pt_regs *regs)2. 3. 4. irq_exit();5. 6. 复制代码C、local_bh_enablelocal_bh_enable就是打开下半部,当然重中之中就是软中断了:1. void local_bh_enable(void)2. 3. _local_bh_enable_ip(unsigned long)_builtin_return_address(0);4. 5.6. static inline void _local_bh_enable_ip(unsigned long ip)7. 8. 9.10. if (unlikely(!in_interrupt() & local_softirq_pending()11. do_softirq();12.13. 14. 复制代码D、在SMP中,当CPU处理完被CALL_FUNCTION_VECTOR处理器间中断所触发的函数时:唔,对多核中CPU的之间的通信不熟,不太清楚这个机制3、do_softirq不论是哪种调用方式,最终都会触发到软中断的核心处理函数do_softirq,它处理当前CPU上的所有软中断。内核将软中断设计尽量与平台无关,但是在某些情况下,它们还是会有差异,先来看一个x86 32位的do_softirq版本:1. asmlinkage void do_softirq(void)2. 3. unsigned long flags;4. struct thread_info *curctx;5. union irq_ctx *irqctx;6. u32 *isp;7.8. /软中断不能在中断上下文内嵌套调用。中断处理程序或下半部采用的是激活方式。9. if (in_interrupt()10. return;11.12. /禁止中断,保存中断标志13. local_irq_save(flags);14. /内核使用一个CPU位图,确实几个软中断可以同时在不同的CPU上运行,包括相同的软中断。例如,15. /NET_RX_SOFTIRQ可以同时跑在多个处理器上。16. /local_softirq_pending用于确定当前CPU的所有位图是否被设置。即是否有软中断等待处理。17. /回想一下经常发生的网卡接收数据处理:当网卡中断落在哪一个CPU上时,与之相应的软中断函数就会在其上执行。18. /从这里来看,实质就是哪个网卡中断落在相应的CPU上,CPU置其软中断位图,这里做相应的检测(这里local_softirq_pending只19. /是一个总的判断,后面还有按位的判断),检测到有相应的位,执行之20. if (local_softirq_pending() 21. /取得线程描述符22. curctx = current_thread_info();23. /构造中断上下文结构,softirq_ctx是每个CPU的软中断上下文24. /static DEFINE_PER_CPU(union irq_ctx *, softirq_ctx);25. /这里先取得当前CPU的软中断上下文,然后为其赋初始值保存当前进程和栈指针26. irqctx = _get_cpu_var(softirq_ctx);27. irqctx-tinfo.task = curctx-task;28. irqctx-tinfo.previous_esp = current_stack_pointer;29.30. /* build the stack frame on the softirq stack */31. /构造中断栈帧32. isp = (u32 *) (char *)irqctx + sizeof(*irqctx);33.34. /call_on_stack切换内核栈,并在中断上下文上执行函数_do_softirq35. call_on_stack(_do_softirq, isp);36. /*37. * Shouldnt happen, we returned above if in_interrupt():38. */39. WARN_ON_ONCE(softirq_count();40. 41.42. /恢复之43. local_irq_restore(flags);44. 复制代码当配置了CONFIG_4KSTACKS,每个进程的thread_union只有4K,而非8K。发生中断时,内核栈将不使用进程的内核栈,而使用每个 cpu的中断请求栈。内核栈将使用每个 cpu的中断请求栈,而非进程的内核栈来执行软中断函数:1. static void call_on_stack(void *func, void *stack)2. 3. asm volatile(xchgl %ebx,%esp n /交换栈指针,中断栈帧的指针stack做为传入参数(%ebx),交换后esp是irq_ctx的栈顶,ebx是进程内核栈的栈4. call *%edi n /调用软中断函数5. movl %ebx,%esp n /恢复之,直接使用movl,而非xchgl是因为函数执行完毕,中断的栈帧指针已经没有用处了6. : =b (stack)7. : 0 (stack),8. D(func)9. : memory, cc, edx, ecx, eax);10. 复制代码PS:所有的这些执行,应该都是在定义4K栈的基础上的:1. #ifdef CONFIG_4KSTACKS2. /*3. * per-CPU IRQ handling contexts (thread information and stack)4. */5. union irq_ctx 6. struct thread_info tinfo;7. u32 stackTHREAD_SIZE/sizeof(u32);8. _attribute_(aligned(PAGE_SIZE);9.10. static DEFINE_PER_CPU(union irq_ctx *, hardirq_ctx);11. static DEFINE_PER_CPU(union irq_ctx *, softirq_ctx);12. 13.14. static void call_on_stack(void *func, void *stack)15. 复制代码是的,这个版本相对复杂,但是如果看了复杂的,再来看简单的,就容易多了,当平台没有定义do_softirq函数时(_ARCH_HAS_DO_SOFTIRQ),内核提供了一个通用的:1. #ifndef _ARCH_HAS_DO_SOFTIRQ2.3. asmlinkage void do_softirq(void)4. 5. _u32 pending;6. unsigned long flags;7.8. if (in_interrupt()9. return;10.11. local_irq_save(flags);12.13. pending = local_softirq_pending();14.15. if (pending)16. _do_softirq();17.18. local_irq_restore(flags);19. 20.21. #endif复制代码无需更多的解释,它非常的简洁。不论是哪个版本,都将调用_do_softirq函数:1. asmlinkage void _do_softirq(void)2. 3. struct softirq_action *h;4. _u32 pending;5. int max_restart = MAX_SOFTIRQ_RESTART;6. int cpu;7.8. /保存位图9. pending = local_softirq_pending();10. /进程记帐11. account_system_vtime(current);12.13. /关闭本地CPU下半部。为了保证同一个CPU上的软中断以串行方式执行。14. _local_bh_disable(unsigned long)_builtin_return_address(0);15. lockdep_softirq_enter();16.17. /获取本地CPU18. cpu = smp_processor_id();19. restart:20. /* Reset the pending bitmask before enabling irqs */21. /清除位图22. set_softirq_pending(0);23.24. /锁中断,只是为了保持位图的互斥,位图处理完毕。后面的代码可以直接使用保存的pending,25. /而中断处理程序在激活的时候,也可以放心地使用irq_stat._softirq_pending。26. /所以,可以开中断了27. local_irq_enable();28.29. /取得软中断向量30. h = softirq_vec;31.32. /循环处理所有的软中断33. do 34. /逐步取位图的每一位,判断该位上是否有软中断被设置。若有,处理之35. if (pending & 1) 36. /保存抢占计数器37. int prev_count = preempt_count();38. kstat_incr_softirqs_this_cpu(h - softirq_vec);39.40. trace_softirq_entry(h, softirq_vec);41. /调用软中断42. h-action(h);43. trace_softirq_exit(h, softirq_vec);44. /判断软中断是否被抢占,如果是,则输出一段错误信息45. if (unlikely(prev_count != preempt_count() 46. printk(KERN_ERR huh, entered softirq %td %s %p47. with preempt_count %08x,48. exited with %08x?n, h - softirq_vec,49. softirq_to_nameh - softirq_vec,50. h-action, prev_count, preempt_count();51. preempt_count() = prev_count;52. 53. /?qsctr,这个是啥东东54. rcu_bh_qsctr_inc(cpu);55. 56. /指向下一个软中断槽位57. h+;58. /移位,取
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 【正版授权】 IEC 60153-2:2025 EN-FR Hollow metallic waveguides - Part 2: Relevant specifications for ordinary rectangular waveguides
- 【正版授权】 ISO/TR 18155:2025 EN Railway applications - Principles of train detection for operations and services
- 校招三方协议后合同
- 服装的出口合同范本
- 村民办民宿合同范本
- 农村厨房转让协议书
- 出库免责协议书模板
- 教育部做好2025届全国普通高校毕业生就业创业工作(全文)易考易错模拟试题(共500题)试卷后附参考答案
- 个人演出协议书范本
- 区域经理聘任协议书
- 高空曲臂车安全操作规程
- 2025年粉尘涉爆培训题库及答案
- 第4章 学前儿童膳食卫生与保健【教学课件】
- DL-T 1476-2023 电力安全工器具预防性试验规程
- (高清版)DZT 0399-2022 矿山资源储量管理规范
- 智慧售电方案
- 数字化人力资源管理系统建设
- 国有企业投资公司绩效考核管理办法
- 模板支撑系统大样图
- T-CAPDA 006-2020 丙酰芸苔素内酯原药
- 家族财富传承法商
评论
0/150
提交评论