linux中断线程化分析【转】

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

linux中断线程化分析【转】

版权声明:本⽂为博主原创⽂章,未经博主允许不得转载。

最近在为3.8版本的内核打RT_PREEMPT补丁,并且优化系统实时性,这篇⽂章主要对RTlinux中中断线程化部分进⾏分析。我们知道在RT_PREEMPT补丁中之所以要将中断

线程化就是因为硬中断的实时性太⾼,会影响实时进程的实时性,所以需要将中断处理程序线程化并设置优先级,使中断处理线程的优先级⽐实时进程优先级低,从⽽提⾼系统

实时性。

⽹上看到⼀些⽹友说在2.6.25.8版本的内核,引⼊了中断线程化,具体是不是2.6.25.8版本开始引⼊中断线程化我没有去求证,因为版本⽐较⽼了改动很多,但据我的查证从

2.6.30开始内核引⼊request_threaded_irq函数,从这个版本开始可以通过在申请中断时为request_irq设置不同的参数决定是否线程化该中断。⽽在2.6.39版内核__setup_irq引⼊

irq_setup_forced_threading函数,开始可以通过# define

force_irqthreads(true)强制使中断线程化,那么从这个版本开始想实现中断线程化就已经变得很简单了,让force_irqthreads为真即可,所以在3.8版本的实时补丁中,正是这⼀段代码实现了中断的线程化:[plain]

1. #ifdef CONFIG_IRQ_FORCED_THREADING

2. -extern bool force_irqthreads;

3. +# ifndef CONFIG_PREEMPT_RT_BASE

4. + extern bool force_irqthreads;

5. +# else

6. +# define force_irqthreads (true)

7. +# endif

8. #else

9. -#define force_irqthreads (0)

10. +#define force_irqthreads (false)

11. #endif

下⾯我们开始正式介绍中断线程化是怎么实现的。

Linux内核常见申请中断的函数request_irq,在内核源码include/linux/interrupt.h头⽂件中可以看到request_irq仅包含return request_threaded_irq(irq, handler, NULL, flags, name,

dev);调⽤,request_threaded_irq函数在源码⽬录kernel/irq/manage.c⽂件中,下⾯通过分析manage.c中各个相关函数解读中断线程化的实现过程。

根据request_irq的调⽤,⾸先分析request_threaded_irq

[plain]

1. int request_threaded_irq(unsigned int irq, irq_handler_t handler,

2. irq_handler_t thread_fn, unsigned long irqflags,

3. const char *devname, void *dev_id)

4. {

5. struct irqaction *action;

6. struct irq_desc *desc;

7. int retval;

8.

9. /*

10. * Sanity-check: shared interrupts must pass in a real dev-ID,

11. * otherwise we'll have trouble later trying to figure out

12. * which interrupt is which (messes up the interrupt freeing

13. * logic etc).

14. */

15. if ((irqflags & IRQF_SHARED) && !dev_id) //共享中断必须有唯⼀确定的设备号,不然中断处理函数找不到发出中断请求的设备,注释写的很清楚

16. return -EINVAL;

17.

18. desc = irq_to_desc(irq);

19. if (!desc)

20. return -EINVAL;

21.

22. if (!irq_settings_can_request(desc) ||

23. WARN_ON(irq_settings_is_per_cpu_devid(desc)))

24. return -EINVAL;

25.

26. if (!handler) { //handler和thread_fn都没有指针传⼊肯定是出错了,有thread_fn⽆handler则将irq_default_primary_handler给handler

27. if (!thread_fn)

28. return -EINVAL;

29. handler = irq_default_primary_handler;

30. }

31.

32. action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);

33. if (!action)

34. return -ENOMEM;

35.

36. action->handler = handler;

37. action->thread_fn = thread_fn;

38. action->flags = irqflags;

39. action->name = devname;

40. action->dev_id = dev_id;

41.

42. chip_bus_lock(desc);

43. retval = __setup_irq(irq, desc, action); //在__setup_irq中确定是否线程化并完成中断处理函数绑定

44. chip_bus_sync_unlock(desc);

45.

46. if (retval)

47. kfree(action);

48.

49. #ifdef CONFIG_DEBUG_SHIRQ_FIXME

50. if (!retval && (irqflags & IRQF_SHARED)) {

51. /*

52. * It's a shared IRQ -- the driver ought to be prepared for it

53. * to happen immediately, so let's make sure....

54. * We disable the irq to make sure that a 'real' IRQ doesn't

55. * run in parallel with our fake.

56. */

57. unsigned long flags;

58.

59. disable_irq(irq);

60. local_irq_save(flags);

61.

62. handler(irq, dev_id);

63.

64. local_irq_restore(flags);

相关文档
最新文档