Linux内核中断系统处理机制-详细分析
⽇期内核版本架构作者内容
2018-8-23Linux-2.6.32Bystander Linux内核中断
⼀、中断概述
是指在CPU正常运⾏期间,由于内外部事件或由程序预先安排的事件引起的CPU暂时停⽌正在运⾏的程序,转⽽为该内部或外部事件或预先安排的事件服务的程序中去,服务完毕后再返回去继续运⾏被暂时中断的程序。
1.1中断类型
同步中断由本⾝产⽣,⼜称为内部中断。这⾥同步是指中断请求信号与代码指令之间的同步执⾏,在⼀条指令执⾏完毕后,CPU才能进⾏中断,不能在执⾏期间。所以也称为异常(exception)。
异步中断是由外部硬件设备产⽣,⼜称为外部中断,与同步中断相反,异步中断可在任何时间产⽣,包括指令执⾏期间,所以也被称为中断(interrupt)。
异常⼜可分为可屏蔽中断(Maskable interrupt)和⾮屏蔽中断(Nomaskable interrupt)。⽽中断可分为故障(fault)、陷阱(trap)、终⽌(abort)三类。
从⼴义上讲,中断⼜可分为四类:中断、故障、陷阱、终⽌。这些类别之间的异同点请参考 表 1。
表 1:中断类别及其⾏为
类别原因异步/同
步
2018高考试题
返回⾏为
中断来⾃I/O设备的信号异步总是返回到下⼀条指令陷阱有意的异常同步总是返回到下⼀条指令故障潜在可恢复的错误同步返回到当前指令
终⽌不可恢复的错误同步不会返回有些参考资料中按照中断来源进⾏分类,如下图所⽰(个⼈建议不采⽤这种⽅式):
图1-1
1.2区分中断号与中断向量
I/O设备把中断信号发送给中断控制器(8259A)时与之相关联的是⼀个中断号,当中断控制器把中断信号发送给CPU时与之关联的是⼀个中断向量。换个⾓度分析就是中断号是从中断控制器层⾯划分,中断向量是从CPU层⾯划分,所以中断号与中断向量之间存在⼀对⼀映射关系。在Intel X86中最⼤⽀
持256种中断,从0到255开始编号,这个8位的编号就是中断向量。其中将0到31保留⽤于异常处理和不可屏蔽中断。
⼆、中断数据处理结构
内核中处理中断主要有三个数据结构,irq_desc,irq_chip和irqaction。
在\include\linux\ irq.h中定义了
1)irq_desc⽤于描述IRQ线的属性与状态,被称为中断描述符。
1/**
2
3 * struct irq_desc - interrupt descriptor
4
5 * @irq: interrupt number for this descriptor
6
bubbles7 * @timer_rand_state: pointer to timer rand state struct
8
9 * @kstat_irqs: irq stats per cpu
10
11 * @irq_2_iommu: iommu with this irq
12
13 * @handle_irq: highlevel irq-events handler [if NULL, __do_IRQ()]
14
15 * @chip: low level interrupt hardware access
16
17 * @msi_desc: MSI descriptor
18
19 * @handler_data: per-IRQ data for the irq_chip methods
20
21 * @chip_data: platform-specific per-chip private data for the chip
22
23 * methods, to allow shared chip implementations
24
25 * @action: the irq action chain
26
27 * @status: status informationhostages
28
29 * @depth: disable-depth, for nested irq_disable() calls
30
31 * @wake_depth: enable depth, for multiple t_irq_wake() callers
32
33 * @irq_count: stats field to detect stalled irqs
34
35 * @last_unhandled: aging timer for unhandled count
36
37 * @irqs_unhandled: stats field for spurious unhandled interrupts
38
39 * @lock: locking for SMP
40
41 * @affinity: IRQ affinity on SMP
42
43 * @node: node index uful for balancing
44
45 * @pending_mask: pending rebalanced interrupts
46
47 * @threads_active: number of irqaction threads currently running
47 * @threads_active: number of irqaction threads currently running
48
49 * @wait_for_threads: wait queue for sync_irq to wait for threaded handlers 50
51 * @dir: /proc/irq/ procfs entry
半半路路52
53 * @name: flow handler name for /proc/interrupts output
54
55 */
56
57struct irq_desc{
58
59 unsigned int irq;
60
61 struct timer_rand_state *timer_rand_state;
62
63 unsigned int *kstat_irqs;
64
65#ifdef CONFIG_INTR_REMAP
66
67 struct irq_2_iommu *irq_2_iommu;
68
69#endif
70
71 irq_flow_handler_t handle_irq;
72
73 struct irq_chip *chip;
74
75 struct msi_desc *msi_desc;
76
77 void *handler_data;
78
79 void *chip_data;
80
theory81 struct irqaction *action; /* IRQ action list */
82
83 unsigned int status; /* IRQ status */
84
85
86 unsigned int depth; /* nested irq disables */
87
88 unsigned int wake_depth; /* nested wake enables */
89
bullshit90 unsigned int irq_count; /* For detecting broken IRQs */
91
92 unsigned long last_unhandled; /* Aging timer for unhandled count */ 93
94 unsigned int irqs_unhandled;
95
96 spinlock_t lock;
97
98#ifdef CONFIG_SMP
99
100 cpumask_var_t affinity;
101
in the way102 unsigned int node;
103
104#ifdef CONFIG_GENERIC_PENDING_IRQ
105
106 cpumask_var_t pending_mask;
107
108#endif
109
110#endif
111
112 atomic_t threads_active;
112 atomic_t threads_active;
113
114 wait_queue_head_t wait_for_threads;
115
116#ifdef CONFIG_PROC_FS
117
118 struct proc_dir_entry *dir;
119
120#endif
121
122 const char *name;
123
124}
2)irq_chip⽤于描述不同类型的中断控制器。
1/**
2
3 * struct irq_chip - hardware interrupt chip descriptor
4
5 *
6
7 * @name: name for /proc/interrupts
8
9 * @startup: start up the interrupt (defaults to ->enable if NULL)
10
11 * @shutdown: shut down the interrupt (defaults to ->disable if NULL)
俄语12
13 * @enable: enable the interrupt (defaults to chip->unmask if NULL)
14
15 * @disable: disable the interrupt (defaults to chip->mask if NULL)
16
17 * @ack: start of a new interrupt
18task
19 * @mask: mask an interrupt source
20
21 * @mask_ack: ack and mask an interrupt source
22
23 * @unmask: unmask an interrupt source
24
25 * @eoi: end of interrupt - chip level
26
27 * @end: end of interrupt - flow level
28
29 * @t_affinity: t the CPU affinity on SMP machines
30
31 * @retrigger: rend an IRQ to the CPU
32
33 * @t_type: t the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
34
35 * @t_wake: enable/disable power-management wake-on of an IRQ
36
37 *
38
39 * @bus_lock: function to lock access to slow bus (i2c) chips
40
41 * @bus_sync_unlock: function to sync and unlock slow bus (i2c) chips
42
43 *
44
45 * @relea: relea function solely ud by UML
46
47 * @typename: obsoleted by name, kept as migration helper
48
49 */
49 */
50
51struct irq_chip {
52
53 const char *name;
54
55 unsigned int (*startup)(unsigned int irq);
56
57 void (*shutdown)(unsigned int irq);
58
59 void (*enable)(unsigned int irq);
60
61 void (*disable)(unsigned int irq);
62
63
64 void (*ack)(unsigned int irq);
65
66 void (*mask)(unsigned int irq);
67
68 void (*mask_ack)(unsigned int irq);
69
70 void (*unmask)(unsigned int irq);
71
72 void (*eoi)(unsigned int irq);
73
74
75 void (*end)(unsigned int irq);
76
77 int (*t_affinity)(unsigned int irq,
78
79 const struct cpumask *dest);
80
81 int (*retrigger)(unsigned int irq);
82
83 int (*t_type)(unsigned int irq, unsigned int flow_type); 84
85 int (*t_wake)(unsigned int irq, unsigned int on);
86
87
88 void (*bus_lock)(unsigned int irq);
89
90 void (*bus_sync_unlock)(unsigned int irq);
91
92
93 /* Currently ud only by UML, might disappear one day.*/ 94
95#ifdef CONFIG_IRQ_RELEASE_METHOD
96
97 void (*relea)(unsigned int irq, void *dev_id);
98
eleanor99#endif
100
101 /*
102
103 * For compatibility, ->typename is copied into ->name.
104
105 * Will disappear.
106
107 */
108
109 const char *typename;
110
111}