上篇博文对中断描述符表(IDT)中异常和非屏蔽中断部分的初始化做了说明,这篇文章将分析外部中断部分的初始化。

在上篇博文中,可以看到,内核在setup_once汇编片段中,对中断和异常部分做了初步的初始化,用early_idt_handlers函数的地址来初始化异常门描述符,用ignore_int函数地址来初始化剩下的中断门描述符。接着,内核在trap_init函数中对IDT做了进一步的初始化,用有效的异常处理程序来初始化中断向量号为0-31的描述符。细心的你应该可以发现,在这一步初始化过程中,仅仅对异常和非屏蔽中断做了初始化(也就是中断向量号前32个),并没有对后256-32=224个中断门描述符初始化,也就是说后244个中断门描述符依然指向的是ignore_int这个无用的函数。下面将分析中断门描述符的最终初始化。首先介绍下interrupt全局数组,该数组中装有了所有的中断处理程序,如下所示:(arch/x86/kernel/entrt_32.S)

  1. .section .init.rodata,"a"
  2. ENTRY(interrupt)
  3. .section .entry.text, "ax"
  4. .p2align
  5. .p2align CONFIG_X86_L1_CACHE_SHIFT
  6. ENTRY(irq_entries_start)
  7. RING0_INT_FRAME
  8. vector=FIRST_EXTERNAL_VECTOR
  9. .rept (NR_VECTORS-FIRST_EXTERNAL_VECTOR+)/
  10. .balign
  11. .rept
  12. .if vector < NR_VECTORS
  13. .if vector <> FIRST_EXTERNAL_VECTOR
  14. CFI_ADJUST_CFA_OFFSET -
  15. .endif
  16. : pushl_cfi $(~vector+0x80) /* Note: always in signed byte range */
  17. .if ((vector-FIRST_EXTERNAL_VECTOR)%) <>
  18. jmp 2f
  19. .endif
  20. .previous
  21. .long 1b
  22. .section .entry.text, "ax"
  23. vector=vector+
  24. .endif
  25. .endr
  26. : jmp common_interrupt
  27. .endr
  28. END(irq_entries_start)
  29.  
  30. .previous
  31. END(interrupt)
  32. .previous

这段代码定义了一个interrupt全局数组,如果不懂ATT汇编的话,这段代码看起来非常吃力。下面笔者粗略分析下这段代码,第1行声明了一个数据段,第2行给这个数据段起了个名字,叫做‘inerrupt’,第3行又声明了一个代码段,该代码段被包在了前边的数据段当中,从第6行可看出这个代码段名字叫做‘irq_entries_start’。接着4-5行说明了代码段对齐的方式,接下来第7行给vector进行赋值,vector=32,实际上,interrup这个数组中存放的全是外部中断,没有异常,异常初始化已经在trap_init函数中完成了,而外部中断的向量号从32开始,所以vector赋值32。接下来在第9,11行大家可以看到出现了伪指令.rept,这个伪指令是循环的意思,你可以把它当成for循环去理解,指令后边的数字是循环次数。这个伪指令实际上告诉编译器要把后边的内容在内存中复制若干次。第9行的(NR_VECTORS-FIRST_EXTERNAL_VECTOR+6)/值为32,要求其后的内容被循环复制32次。因此第9行和第11行合起来,就相当于一个双重for循环,总共循环32*7=224次,这刚好就是外部中断向量号的数量,每执行一次内部循环,就将一个外部中断处理程序放入了一个数组元素中。接着第20行出现了.previous伪指令。该指令的意思是返回到上一个段中,在这里就是要返回到interrupt数据段中,第21行,在interrupt数据段中定义了一个long型数据,值为标号1,标号1实际上就是第16行代码的地址。接着第22行又回到了当前代码段中,让vector自加1,然后第25行进入内重循环的下一次循环。第26行,标号2的这个指令夹在了内外两重循环之间,说明每执行7次内循环就要将jmp common_interrupt复制一次。然后第27行进入外重循环的下一次循环。总共执行32*7次循环后,这段代码就结束了。通过使用.preivous伪指令,最终实际上就定义了两个数组,一个是interrput数组,该数组的每个元素均为.long 1b(第21行),另外一个数组是irq_entries_start,该数组每个元素中放入了若干条汇编指令(16-18行,26行)。这就是.previous的用处,每在irq_entries_start数组中初始化完一个元素,立马返回到interrupt数组中定义一个指向irq_entries_start数组中刚初始化过的元素的指针(.long 1b),作为interrupt数组的元素。最终interrput数组中存放了224个指针(每个中断处理程序的地址),分别指向了irq_entries_start数组中的对应元素。irq_entries_start数组每个元素存放的是几条汇编指令(这些汇编指令就是中断处理程序的开头公共部分)。而且,通过第26行,可以看到,irq_entries_start数组每个元素都包含jmp common_interrupt指令,跳入到一段公共的代码中。

上边的工作,内核只是把所有的外部中断处理程序用两个数组管理起来了,接下来,就要在IDT(中断描述符表)中初始化所有外部中断的门描述符。代码如下:(arch/x86/kernel/irqinit.c)

  1. void __init native_init_IRQ(void)
  2. {
  3. int i;
  4.  
  5. /* Execute any quirks before the call gates are initialised: */
  6. x86_init.irqs.pre_vector_init();
  7.  
  8. apic_intr_init();
  9.  
  10. /*
  11. * Cover the whole vector space, no vector can escape
  12. * us. (some of these will be overridden and become
  13. * 'special' SMP interrupts)
  14. */
  15. i = FIRST_EXTERNAL_VECTOR;
  16. for_each_clear_bit_from(i, used_vectors, NR_VECTORS) {
  17. /* IA32_SYSCALL_VECTOR could be used in trap_init already. */
  18. set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]);
  19. }
  20.  
  21. if (!acpi_ioapic && !of_ioapic)
  22. setup_irq(, &irq2);
  23.  
  24. #ifdef CONFIG_X86_32
  25. irq_ctx_init(smp_processor_id());
  26. #endif
  27. }

从16-19行,可以看出,用interrupt数组中存放的所有中断处理程序地址来初始化IDT的中断门描述符。set_intr_gate函数上篇博文已经分析过来,这里不再分析。

至此,所有IDT中的异常和中断门描述符就初始化完成了。

中断——中断描述符表的定义和初始化(二) (基于3.16-rc4)的更多相关文章

  1. 中断——中断描述符表的定义和初始化(一) (基于3.16-rc4)

    1.中断描述符表的定义(arch/x86/kernel/traps.c) gate_desc debug_idt_table[NR_VECTORS] __page_aligned_bss; 定义的描述 ...

  2. linux中断源码分析 - 初始化(二)

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 本篇文章主要讲述源码中是如何对中断进行一系列的初始化的. 回顾 在上一篇概述中,介绍了几个对于中断来说非常重要的 ...

  3. linux中断子系统:中断号的映射与维护初始化mmap过程

    本文均属自己阅读源代码的点滴总结.转账请注明出处谢谢. 欢迎和大家交流.qq:1037701636 email:gzzaigcn2009@163.com 写在前沿: 好久好久没有静下心来整理一些东西了 ...

  4. js二维数组定义和初始化的三种方法总结

    js二维数组定义和初始化的三种方法总结 方法一:直接定义并且初始化,这种遇到数量少的情况可以用var _TheArray = [["0-1","0-2"],[& ...

  5. Linux内核学习之中断 中断本质【转】

    转自:http://www.linuxidc.com/Linux/2011-11/47657.htm [中断概述] 中断本质上是一种特殊的电信号,由硬件设备发向处理器.异常和中断的不同是异常在产生时必 ...

  6. 软中断与硬中断 & 中断抢占 中断嵌套

    参考了这篇文章:http://blog.csdn.net/zhangskd/article/details/21992933 从本质上来讲,中断是一种电信号,当设备有某种事件发生时,它就会产生中断,通 ...

  7. 你好,C++(7)第三部分 C++世界众生相 3.2.1 变量的定义与初始化

    第3部分 C++世界众生相 在听过了HelloWorld.exe的自我介绍,完成了与C++世界的第一次亲密接触后,大家是不是都急不可待地想要一试身手,开始编写C++程序了呢?程序的两大任务是描述数据和 ...

  8. C++中数组定义及初始化

    一.一维数组 静态 int array[100]; 定义了数组array,并未对数组进行初始化 静态 int array[100] = {1,2}: 定义并初始化了数组array 动态 int* ar ...

  9. C语言中二维字符数组的定义和初始化

    本篇日志关于二维字符数组的定义和初始化.我相信这篇文章属于菜鸟级的,高手请直接无视. 一般来说,我们可能会希望定义一个二维字符数组并且在定义的时候就用一些字符串来初始化它.比如说: ][MAX_LEN ...

随机推荐

  1. Matlab中添加搜索目录

    一.问题来源 来自于一份大规模hash图像检索代码. 二.问题解析 2.1 添加目录 addpath('./utils/'); 2.2 添加目录及其子目录 addpath(genpath('./uti ...

  2. (转)基于即时通信和LBS技术的位置感知服务(一):提出问题及解决方案

    一.前言.提出问题 公司最近举行2011年度创新设计大赛,快年底了正打算写写2010年以来Android开发的心得与经验,正好同事出了个点子:假如A和B两个人分别在不同的地点,能不能实现这样的功能,让 ...

  3. Unity3D调用第三方SDK(之一)从eclipse到Unity3D 友盟

    原地址:http://www.360doc.com/content/14/0120/14/11670799_346638215.shtml 篇展示在Unity3D中调用友盟SDK的实现方法. 首先附上 ...

  4. 阿里云PHP Redis代码示例

    测试代码示例 <?php /* 这里替换为连接的实例host和port */ $host = "localhost"; $port = 6379; /* 这里替换为实例id和 ...

  5. 第二个C语言代码

    有问题,还没找出哪里出错了       输入一串字符,问号结束 统计1~9各出现的次数 ******************************************************** ...

  6. Django用户认证系统(一)User对象

    User对象 User对象是认证系统的核心.用户对象通常用来代表网站的用户,并支持例如访问控制.注册用户.关联创建者和内容等.在Django认证框架中只有一个用户类,例如超级用户('superuser ...

  7. P147、面试题26:复杂链表的复制

    题目:请实现ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表.在复杂链表中,每个结点除了有一个m_pNext指针指向下一个结点外,还有一个 ...

  8. P125、面试题19:二叉树的镜像

    题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像二叉树结点的定义如下:struct BinaryTreeNode{       int     m_nValue;       BinaryTr ...

  9. A9裸机

    Tiny4412裸机程序之操作ICache 一.首先普及一下什么是Cache 基于程序访问的局限性,在主存和CPU通用寄存器之前设置了一类高速的.容量较小的存储器,把正在执行的指令地址附件的一部分指令 ...

  10. 安装安装.net framework过程中出现的问题

    1.安装Microsoft..net framework2.0 SP2 出现 必须使用控制面板中的打开或关闭windows功能,安装或配置.net framework2.0 SP2 原因:可以打开控制 ...