嵌入式系统 中断.pptVIP

  1. 1、本文档共54页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  5. 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  6. 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  7. 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  8. 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
为了有助于读者对中断实现过程的理解,下面介绍几条相关的汇编指令: (1)调用过程指令CALL 指令格式: CALL 过程名 说明:在取出CALL指令之后及执行CALL指令之前,使指令指针寄存器EIP指向紧接CALL指令的下一条指令。CALL指令先将EIP值压入栈内,再进行控制转移。当遇到RET指令时,栈内信息可使控制权直接回到CALL的下一条指令 (2)调用中断过程的指令INT 指令格式:INT 中断向量 说明:EFLAG、CS及EIP寄存器被压入栈内。控制权被转移到由中断向量指定的中断处理程序。在中断处理程序结束时,IRET指令又把控制权送回到刚才执行被中断的地方。 (3)中断返回指令IRET 指令格式:IRET 说明:IRET与中断调用过程相反:它将EIP、CS及EFLAGS寄存器内容从栈中弹出,并将控制权返回到发生中断的地方。IRET用在中断处理程序的结束处。 (4)加载中断描述符表的指令LIDT 格式:LIDT 48位的伪描述符 说明:LIDT将指令中给定的48位伪描述符装入中断描述符寄存器IDTR。 用户进程可以通过INT指令发出一个中断请求,其中断请求向量在0~255之间。为了防止用户使用INT指令模拟非法的中断和异常,必须对中断描述符表进行谨慎的初始化。其措施之一就是将中断门或陷阱门中的请求特权级DPL域置为0。如果用户进程确实发出了这样一个中断请求,CPU会检查出其当前特权级CPL(3)与所请求的特权级DPL(0)有冲突,因此产生一个“通用保护”异常。 但是,有时候必须让用户进程能够使用内核所提供的功能(比如系统调用),也就是说从用户态进入内核态,这可以通过把中断门或陷阱门的DPL域置为3 来达到。 当计算机运行在实模式时,中断描述符表被初始化,并由BIOS使用。然而,一旦真正进入了Linux内核,中断描述符表就被移到内存的另一个区域,并为进入保护模式进行预初始化:用汇编指令LIDT对中断向量表寄存器IDTR进行初始化,即把IDTR置为0。把中断描述符表IDT的起始地址装入IDTR 用setup_idt()函数填充中断描述表中的256个表项。在对这个表进行填充时,使用了一个空的中断处理程序。因为现在处于初始化阶段,还没有任何中断处理程序,因此,用这个空的中断处理程序填充每个表项。 在对中断描述符表进行预初始化后, 内核将在启用分页功能后对IDT进行第二遍初始化,也就是说,用实际的陷阱和中断处理程序替换这个空的处理程序。一旦这个过程完成,对于每个异常,IDT都由一个专门的陷阱门或系统门,而对每个外部中断,IDT都包含专门的中断门。 IDT表项的设置是通过_set_gaet()函数实现的,在此,我们给出如何调用该函数在IDT表中插入一个门: (1) 插入一个中断门 void set_intr_gate(unsigned int n, void *addr) { _set_gate(idt_table+n,14,0,addr); } 其中,idt_table是中断描述符表IDT在程序中的符号表示, n表示在第n个表项中插入一个中断门。这个门的段选择符设置成代码段的选择符,DPL域设置成0,14表示D标志位为1(表示32位)而类型码为110,所以set_intr_gate()设置的是中断门,偏移域设置成中断处理程序的地址addr。 (2) 插入一个陷阱门 static void __init set_trap_gate(unsigned int n, void *addr) { _set_gate(idt_table+n,15,0,addr); } 在第 n个表项中插入一个陷阱门。这个门的段选择符设置成代码段的选择符,DPL域设置成0,15表示D标志位为1而类型码为111,所以set_trap_gate()设置的是陷阱门,偏移域设置成异常处理程序的地址addr。 (3) 插入一个系统门 ? static void __init set_system_gate(unsigned int n, void *addr) { _set_gate(idt_table+n,15,3,addr); } 在第 n个表项中插入一个系统门。这个门的段选择符设置成代码段的选择符,DPL域设置成3,15表示D标志位为1而类型码为111,所以set_system_gate()设置的也是陷阱门,但因为DPL为3,因此,系统调用在用户态可以通过“INT 0x80”顺利穿过系统门,从而进入内核态。 大多数情况下,为了控制一个寻常的硬件设备,小任务机制是实现下半部的最佳选择。小任务可以动态创建,使用方便,执行起来也比较快。

文档评论(0)

xx88606 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档