分类: LINUX

在系统初始化期间,trap_init()函数将对中断描述符表IDT进行第二次初始化(第一次只是建一张IDT表,让其指向ignore_intr函数),而在这次初始化期间,系统的0~19号中断(用于分NMI和异常的中断向量)均被设置好。与此同时,用于系统调用的0x80号向量也已被设置。
然而,对于外部中断的初始化 却没有在这个函数中进行。而是在函数init_IRQ中。
 
仔细想一想内核这样做,的确是使代码清晰又有条理。
1)trap_init -----> 内部中断异常和NMI(中断向量号:0~19)
2) init_IRQ   -----> 外部可屏蔽中断  (中断向量号:32~127,129~238)
 
在init_IRQ函数中,对IDT中断描述符表进行了第三次完善(把相应的外部中断对应的中断向量进行填充)
  1. 410 for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
  2. 411 int vector = FIRST_EXTERNAL_VECTOR + i;
  3. 412 if (i >= NR_IRQS)
  4. 413 break;
  5. 414 if (vector != SYSCALL_VECTOR)
  6. 415 set_intr_gate(vector, interrupt[i]);
  7. 416 }
上述代码解释:
      FIRST_EXTERNAL_VECTOR =0x20;
  http://lxr.linux.no/linux+v3.10/arch/x86/include/asm/irq_vectors.h#L35
      设置中断向量号32---NR_IRQS相应的中断处理程序地址为数组interrupt[i]的内容。(除去128号中断向量,已经这个向量号已经被用于系统调用)。
我们看一下interrupt数组的定义:这段程序时用汇编写的。
  1. 540 .data
  2. 541 ENTRY(interrupt)
  3. 542 .text
  4. 543
  5. 544 vector=0
  6. 545 ENTRY(irq_entries_start)
  7. 546 RING0_INT_FRAME
  8. 547 .rept NR_IRQS
  9. 548 ALIGN
  10. 549 .if vector
  11. 550 CFI_ADJUST_CFA_OFFSET -4
  12. 551 .endif
  13. 552 1: pushl $~(vector)
  14. 553 CFI_ADJUST_CFA_OFFSET 4
  15. 554 jmp common_interrupt
  16. 555 .data
  17. 556 .long 1b
  18. 557 .text
  19. 558 vector=vector+1
  20. 559 .endr

上面的代码开起来很乱,我们整理一下,使其更加易读,但是又不失其本质。

    1. .data
    2. ENTRY(interrupt)
    3. .long 1b //注意 如果把数据段放在这里那么1b要改为1f了,而且失去循环执行NR_IRQS次的功能。
    4. //我们只能人为的把他们想象成被循环执行了NR_IRQS次 :)

  1. .text
  2. vector=0
  3. ENTRY(irq_entries_start)
  4. .rept NR_IRQS
  5. 1: pushl $~(vector)
  6. jmp common_interrupt
  7. vector=vector+1

我们把数据段放在一起,代码段放在一起。注意这里的代码段是用来初始化数据段的。

我们看到:interrupt作为一个内存标签,其内容为代码段标号1所表示的地址。同时我们也注意到这个interrupt数组的所有项的内容都是一样的:全部为“标号1”的符号地址。

每次外部中断来临时,硬件自动根据PIC或者APIC送出来的中断类型码(中断向量号)去查找中断描述符表的相应项,然后得到interrupt[n]的内容,继而转去执行标号1地址的代码,而标号1的代码仅将中断号取反后压入栈中,后立马跳到common_interupt标号处去执行。至于为什么要把中断向量号取反后压栈,则是由于内核用正的相应号去表示系统调用号,用负号来表示中断号。

细心的你有可能发现了一个问题:上述代码片段只是向interrupt表示的内存地址处存入大量重复的4字节数据,却没有象C语言定义数组那样定义interrupt[NR_IRQS-1],那么set_intr_gate这样的函数是如何确切的指导interrupt是一个数组呢,而且数组的内容是函数指针?

例如:set_intr_gate(vector,interrupt[i]);是如何取interrupt[i]内容呢?

啰嗦了这么半天...

如下一个声明就搞定了。

extern void (*interrupt[NR_IRQS])(void);//函数指针数组

  1. 566 common_interrupt:
  2. 567 SAVE_ALL
  3. 568 TRACE_IRQS_OFF
  4. 569 movl %esp,%eax
  5. 570 call do_IRQ
  6. 571 jmp ret_from_intr
  7. 572 CFI_ENDPROC

common_interrupt首先执行宏SAVE_ALL保存中断处理程序可能用到的寄存器(注意:cs eip ss esp由硬件自动保存)然后把栈顶指针传给eax寄存器后(eax寄存器内容将作为do_IRQ函数的参数)调用do_IRQ进行中断处理,返回后

执行ret_from_intr从中断返回。

[fW]中断处理函数数组interrupt[]初始化的更多相关文章

  1. C函数数组元素初始化

    初始化时,可随意指定初始化的元素或者元素的范围. 附gnu c 手册. http://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html 代码: t ...

  2. [fw]LINUX中断描述符初始化

    LINUX中断描述符初始化 @CopyLeft by ICANTH,I Can do ANy THing that I CAN THink!~ Author: WenHui, WuHan Univer ...

  3. 关于数组的初始化memset函数

    关于数组的初始化memset函数 其实memset复制时按bit8个8个的赋值,有兴趣的可以自己百度.

  4. 裸板中中断异常处理,linux中断异常处理 ,linux系统中断处理的API,中断处理函数的要求,内核中登记底半部的方式

    1.linux系统中的中断处理  1.0裸板中中断异常是如何处理的?     以s5p6818+按键为例          1)按键中断的触发        中断源级配置            管脚功 ...

  5. bootloader启动代码init.s解析----IRQ中断处理函数

    bootloader启动代码init.s解析----IRQ中断处理函数 init.s源代码如下: ;///////////////////////////////////////////// ;opt ...

  6. 痞子衡嵌入式:以i.MXRT1xxx的GPIO模块为例谈谈中断处理函数(IRQHandler)的标准流程

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是以i.MXRT的GPIO模块为例谈谈中断处理函数(IRQHandler)的标准流程. 在痞子衡旧文 <串口(UART)自动波特率识 ...

  7. Linux驱动实践:中断处理函数如何【发送信号】给应用层?

    作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++.嵌入式.Linux. 关注下方公众号,回复[书籍],获取 Linux.嵌入式领域经典书籍:回复[PDF],获取所有原创文章( PDF 格式). ...

  8. 【转】中断处理函数中不用disable_irq而用disable_irq_nosync原因

    原文网址:http://blog.csdn.net/skyflying2012/article/details/8265869 今天在写触摸屏驱动时在中断处理函数中使用disable_irq关中断发现 ...

  9. -1-1 java 基础语法 java关键字 java 注释 常量 语句 运算符 函数 数组定义

    Java语言基础组成 关键字 标识符 注释 常量和变量 运算符 语句 函数 数组 关键字 定义:被Java语言赋予了特殊含义的单词 特点:关键字中所有字母都为小写 用于定义数据类型的关键字 class ...

随机推荐

  1. 【学习总结】GirlsInAI ML-diary day-21-初识 Numpy, Matplotlib, Seanborn [柱状图、折线图、箱图]

    [学习总结]GirlsInAI ML-diary 总 原博github链接-day21 初识 Numpy, Matplotlib, Seanborn [柱状图.折线图.箱图] 一.Titanic练习赛 ...

  2. Django学习——开发你的第一个Django应用2

    接着上一节的内容来说.我们将继续关注与上一节制作的polls应用以及Django自动产生额度管理网站. 产生一个管理员用户 首先我们需要产生一个管理员用户,运行如下命令: python manage. ...

  3. IDS4授权分析

    一.授权过程的场景名词 RO (resource owner): 资源所有者:用户. Resource Owner:简单理解为资源拥有者,文中称“user”: RS (resource server) ...

  4. python数字图像处理(四) 频率域滤波

    import matplotlib.pyplot as plt import numpy as np import cv2 %matplotlib inline 首先读入这次需要使用的图像 img = ...

  5. Center os vi

    vi /etc/virc set nu 设置所有文件显示行号 :1,$s/after/befer/g  全局替换 :%s/after/befer/g 全局替换 yy 复制一行 p 粘贴 yw 复制一个 ...

  6. Flutter-Text

    text的主要属性有:textAlign,maxLines,overflow等. Text( "hello flutter!", TextAlign:TextAlign.cente ...

  7. Java字符串流学习

    字符串流 定义:字符串流,以一个字符为数据源,来构造一个字符流. 作用:在Web开发中,我们经常要从服务器上获取数据,数据返回的格式通过一个字符串(XML.JSON),我们需要把这个字符串构造为一个字 ...

  8. session有效时间

    request.getSession().setMaxInactiveInterval(-1);//session不失效 request.getSession().setMaxInactiveInte ...

  9. Java double转long方法

    Java double转long方法 double random = Math.round(Math.random()*10000); long l = new Double(random).long ...

  10. 【leetcode】668. Kth Smallest Number in Multiplication Table

    题目如下: 解题思路:几乎和[leetcode]719. Find K-th Smallest Pair Distance 的方法一样.只不过一个是减法一个是乘法,还有一点区别是[leetcode]7 ...