中断门初始化(init_IRQ)
来源:互联网 发布:淘宝网店计划 编辑:程序博客网 时间:2024/06/06 16:38
1,中断门的设置是在init_IRQ中完成
linux-2.6.11.12\init\main.c:start_kernel->init_IRQ
2,init_IRQ(linux-2.6.11.12\arch\i386\kernel\i8259.c)
1)for循环用于设置中断门,但跳过用于设置系统调用的陷阱门中断向量(SYSCALL_VECTOR,在trap_init中初始化),并跳过CPU使用的0~19异常和非屏蔽中断向量(用于设置陷阱门的中断向量,由trap_init初始化)以及Intel保留的20~31向量。即设置中断门从设置断向量FIRST_EXTERNAL_VECTOR(0x20=32)开始,共NR_IRQS(当没有定义CONFIG_X86_IO_APIC时,只利用了从32号开始的15个(与 8259A中的15个IRQ相对应),即NR_IRQS=15);
2)interrupt[i]为中断处理函数,在linux-2.6.11.12\arch\i386\kernel\entry.S中定义:
分析如下:
首先342行和352行都处于.data段,虽然看起来它们是隔开的,但实际上被gcc安排在了连续的数据段内存 中,同理在代码段内存中,354行与350行的指令序列也是连续存储的。另外,348-354行会被gcc展开NR_IRQS次,因此每次352行都会存储一个新的指针,该指针指向每个349行展开的新对象。最后在代码段内存中连续存储了NR_IRQS个代码片断,首地址由 irq_entries_start指向。而在数据段内存中连续存储了NR_IRQS个指针,首址存储在interrupt这个全局变量中。这样,例如 IRQ号是0 (从init_IRQ()调用,它对应的中断向量是FIRST_EXTERNAL_VECTOR)的中断通过中断门后会触发 interrput[0],从而执行:
pushl 0-256
jmp common_interrupt
的代码片断,进入到Linux内核安排好的中断入口路径。
首先342行和352行都处于.data段,虽然看起来它们是隔开的,但实际上被gcc安排在了连续的数据段内存 中,同理在代码段内存中,354行与350行的指令序列也是连续存储的。另外,348-354行会被gcc展开NR_IRQS次,因此每次352行都会存储一个新的指针,该指针指向每个349行展开的新对象。最后在代码段内存中连续存储了NR_IRQS个代码片断,首地址由 irq_entries_start指向。而在数据段内存中连续存储了NR_IRQS个指针,首址存储在interrupt这个全局变量中。这样,例如 IRQ号是0 (从init_IRQ()调用,它对应的中断向量是FIRST_EXTERNAL_VECTOR)的中断通过中断门后会触发 interrput[0],从而执行:
pushl 0-256
jmp common_interrupt
的代码片断,进入到Linux内核安排好的中断入口路径。
3) set_intr_gate这是中断门,14表示0b1110,即表示中断门;0表示设置dpl=0(用于硬件中断,DPL为0,不允许用户态直接使用int指令访问);idt_table+n表示中断向量n对应的idt表中的位置;__KERNEL_CS表示内核代码段。
4),调用pre_intr_init_hook()函数来初始化16个可屏蔽中断的 irq_desc结构体(在Linux之中对于每一个中断有两个重要的数据结构与之对应,他们分别是中断门描述符idt_table和中断请求描述符irq_desc,所谓的中断初始化也就是对这两个数据结构进行初始化);
Linux支持多个外设共享一个IRQ,为了维护中断向量和中断服务例程(ISR)之间的映射关系,Linux用一个irq_desc_t数据结构来描述,叫做IRQ描述符。
status描述中短线状态:
#define IRQ_INPROGRESS 1 /* 正在执行这个IRQ的一个处理程序*/
#define IRQ_DISABLED 2 /* 由设备驱动程序已经禁用了这条IRQ中断线 */
#define IRQ_PENDING 4 /* 一个IRQ已经出现在中断线上,且被应答,但还没有为它提供服务 */
#define IRQ_REPLAY 8 /* 当Linux重新发送一个已被删除的IRQ时 */
#define IRQ_AUTODETECT 16 /* 当进行硬件设备探测时,内核使用这条IRQ中断线 */
#define IRQ_WAITING 32 /*当对硬件设备进行探测时,设置这个状态以标记正在被测试的irq */
#define IRQ_LEVEL 64 /* IRQ level triggered */
#define IRQ_MASKED 128 /* IRQ masked - shouldn't be seen again */
#define IRQ_PER_CPU 256 /* IRQ is per CPU */
#define IRQ_DISABLED 2 /* 由设备驱动程序已经禁用了这条IRQ中断线 */
#define IRQ_PENDING 4 /* 一个IRQ已经出现在中断线上,且被应答,但还没有为它提供服务 */
#define IRQ_REPLAY 8 /* 当Linux重新发送一个已被删除的IRQ时 */
#define IRQ_AUTODETECT 16 /* 当进行硬件设备探测时,内核使用这条IRQ中断线 */
#define IRQ_WAITING 32 /*当对硬件设备进行探测时,设置这个状态以标记正在被测试的irq */
#define IRQ_LEVEL 64 /* IRQ level triggered */
#define IRQ_MASKED 128 /* IRQ masked - shouldn't be seen again */
#define IRQ_PER_CPU 256 /* IRQ is per CPU */
handler:指向hw_interrupt_type描述符,这个描述符是对中断控制器的描述。
action:指向一个单向链表的指针,这个链表就是对中断服务例程进行描述的irqaction结构。
depth:如果启用这条IRQ中断线,depth则为0,如果禁用这条IRQ中断线不止一次,则为一个正数。每当调用一次disable_irq(),该函数就对这个域的值加1,如果depth等于0,该函数就禁用这条IRQ中断线。相反,每当调用enable_irq()函数时,该函数就对这个域的值减1;如果depth变为0,该函数就启用这条IRQ中断线。
lock:保护该数据结构的自旋锁。
action:指向一个单向链表的指针,这个链表就是对中断服务例程进行描述的irqaction结构。
depth:如果启用这条IRQ中断线,depth则为0,如果禁用这条IRQ中断线不止一次,则为一个正数。每当调用一次disable_irq(),该函数就对这个域的值加1,如果depth等于0,该函数就禁用这条IRQ中断线。相反,每当调用enable_irq()函数时,该函数就对这个域的值减1;如果depth变为0,该函数就启用这条IRQ中断线。
lock:保护该数据结构的自旋锁。
irqaction结构(next指向下一个irqaction结构):
handler:指向一个具体I/O设备的中断服务例程。这是允许多个设备共享同一中断线的关键域。
flags:用一组标志描述中断线与I/O设备之间的关系。
SA_INTERRUPT
中断处理程序必须以禁用中断来执行
SA_SHIRQ
该设备允许其中断线与其他设备共享,注意在同一个给定线上注册的每个处理程序必须制定这个标志,否则,在每条线上只能有一个中断处理程序。
SA_SAMPLE_RANDOM
可以把这个设备看作是随机事件发生源;因此,内核可以用它做随机数产生器。(用户可以从/dev/random 和/dev/urandom设备文件中取得随机数而访问这种特征)
SA_PROBE
内核在执行硬件设备探测时正在使用这条中断线。
name:I/O设备名(通过读取/proc/interrupts文件,可以看到,在列出中断号时也显示设备名。)
dev_id:指定I/O设备的主设备号和次设备号。当一个中断处理程序需要从一个中断线上注册(dev_id作为注册函数request_irq的入参)或释放时,dev_id将提供唯一的标示。如删除中断程序时,将会删除dev_id指定的这一个,如果没有这个参数,内核不可能知道在给定的中断线上到底要删除哪一个处理程序。如果无需共享中短线,那么将参数赋值为NULL就可以了。
flags:用一组标志描述中断线与I/O设备之间的关系。
SA_INTERRUPT
中断处理程序必须以禁用中断来执行
SA_SHIRQ
该设备允许其中断线与其他设备共享,注意在同一个给定线上注册的每个处理程序必须制定这个标志,否则,在每条线上只能有一个中断处理程序。
SA_SAMPLE_RANDOM
可以把这个设备看作是随机事件发生源;因此,内核可以用它做随机数产生器。(用户可以从/dev/random 和/dev/urandom设备文件中取得随机数而访问这种特征)
SA_PROBE
内核在执行硬件设备探测时正在使用这条中断线。
name:I/O设备名(通过读取/proc/interrupts文件,可以看到,在列出中断号时也显示设备名。)
dev_id:指定I/O设备的主设备号和次设备号。当一个中断处理程序需要从一个中断线上注册(dev_id作为注册函数request_irq的入参)或释放时,dev_id将提供唯一的标示。如删除中断程序时,将会删除dev_id指定的这一个,如果没有这个参数,内核不可能知道在给定的中断线上到底要删除哪一个处理程序。如果无需共享中短线,那么将参数赋值为NULL就可以了。
next:指向irqaction描述符链表的下一个元素。共享同一中断线的每个硬件设备都有其对应的中断服务例程,链表中的每个元素就是对相应设备及中断服务例程的描述。
irq:IRQ线。
irq:IRQ线。
由上述代码可知,初始化时让所有的中断线都处于禁用状态,每条中断线上还没有任何中断服务例程(action为0,即链表为空),因为中断线被禁用,因此depth为1。当调用request_irq注册中断时,将覆盖掉这些初始值。
0 0
- 中断门初始化(init_IRQ)
- 中断子系统( 1)初始化
- 中断初始化
- uClinux for bf561中的中断处理(1):中断初始化
- 又是中断(三)-初始化
- (转)Linux的中断的初始化
- Linux中断子系统-中断初始化
- eboot中的中断初始化
- 软中断初始化
- 初始化定时器中断
- 初始化中断描述表
- 中断系统的初始化
- arm linux 中断初始化
- 中断队列的初始化
- 海思3516中断初始化
- rt5350 中断初始化
- 初始化bf518中断
- 初始化定时器中断
- docker在centos上的安装和使用
- linux查看本机IP、gateway、dns
- 关于block 循环引用 weakSelf
- 配置asp.net 2.0的项目到IIS7
- Python核心数据类型——布尔型
- 中断门初始化(init_IRQ)
- Linux下*.tar.gz文件解压缩命令
- quickcocos2dx 3.3 拉伸适配
- PHP self与static区别
- 存储过程例子(1)
- Fragment 点击穿透 解决办法
- opencv3.0.0 for android .判断两张图片是否一致
- HTML5初学者路线图
- liftweb整合ckfinder进行文件上传与管理