Chinaunix首页 | 论坛 | 博客
  • 博客访问: 500147
  • 博文数量: 104
  • 博客积分: 3045
  • 博客等级: 少校
  • 技术积分: 1230
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-29 10:18
文章分类

全部博文(104)

文章存档

2011年(72)

2010年(1)

2009年(1)

2008年(30)

分类: LINUX

2008-03-19 00:51:35

异常和中断

  同步:指令执行时cpu控制单元产生的,说他是同步是因为只有指令终止后cpu才发生中断;

  异步:其他硬件设备依照cpu时钟产生的。所以,同步和异步中断分别称为异常和中断。

  中断 :可屏蔽中断(Maskeble interrupt) 可屏蔽的和非屏蔽的

  异常 :故障(Fault) 缺页异常处理程序

        陷阱(Trap) 当执行没有必要重新执行已终止的指令时,出发陷阱。

        异常终止(Abort) 用于报告严重的错误。

        编程异常 Programmed exception)在编程者发出请求是发生。是由int (int3)指令时触

    高级可编程中断控制器(Advanced Programmable Interrupt Controller APIC )

  中断和异常处理程序的嵌套执行

   中断处理程序从不执行可以导致缺页的异常的操作,一个中断处理程序可以抢占其他的中断处理程序,也可以抢占异常处理程序。异常处理程序从不抢占中断处理程序。为防止用户进程试图发生一个中断信号,可以通过把中断门后陷阱们描述符的DPL 字段设置成0来实现。如果进程试图发出其中的一个中断信号,使DPL CPL的值有冲突,产生一个通用保护异常。少数情况下,用户进程必须发出一个编程异常 只要把中断或陷阱门描述符的DPL设为3

陷阱门和中断门

  1 中断门

  2 系统门 用户态的进程可以访问的一个intel陷阱门。通过系统门来激活四个linux的异常处理程序,向量  

          3 4 5 128

  3 陷阱门 用户态的进程不能访问的一个intel陷阱门。

  set_intr_gate(n, addr);  set_system__gate(n,addr); set_trap_gate(n, addr); 以上三组函数用来在IDT中插入门。

IDT的初步初始化

   setup_idt();汇编语言函数用同一个中断门(即指向ignore_int()的中断处理程序)来填充256idt_table表项:ignore_int()从不被执行,在控制台或日志文件中出现“Unknown interrupt”的消息来标志出现一个硬件的问题,或者是一个内核的问题(一个中断或异常未被适当处理)。

异常处理

   在两种情况下,linux利用CPU异常更有效的管理硬件资源。

   第一,保存FPU, MMX ,XMM寄存器中浮点协处理器。设备不可用异常cr0寄存器的TS标志一起用来把新值装入浮点寄存器。

   第二, 缺页情况。

异常或中断的处理过程

  1 保存寄存器的值

  2 进入和离开异常处理程序,执行异常处理程序的C函数名总是由do_前缀和处理程序名组成。其中大部分函数把硬件出错码和异常向量保存在当前进程的描述符中,然后,向当前进程发送一个适当的信号。异常处理程序终止后,当前进程就关注这个信号。该信号要么由进程自己的信号处理程序来处理,要么由内核来处理。在后中情况下内核一般会杀死这个进程。

  3 中断有三种类型 I/O中断 时钟中断 处理器间的中断

    I/O 中断处理  

 中断处理程序可以分为

           IRQ共享

           IRQ 动态分配: 中断处理程序是代表进程执行的,他所代表的进程总是处在TASK_RUNNING     态,不能出现僵死状态。

 linux把紧随中断要执行的操作分为三类:

      紧急的: 必须在禁止可屏蔽中断的情况下。

      非紧急的: 必须在开中断的情况下。

      非紧急可延迟的:

所有I/O 中断处理程序必须执行四个形同的基本步骤

 1 砸内核态堆栈中保存IRQ 的值和寄存其的的内容。

 2 为正在给IRQ线服务的PIC发送一个应答,这将允许PIC进一步发出中断。

 3 执行共享这个IRQ的所有设备的中断服务例程

 4 跳到 ret_from_intr()的地址后终止。

中断向量

   0~19 0x0~0x13)    非屏蔽中断和向量

   20~31 OX14~0X1F)   intel保留

   32~127 0x20~0x7f   外部中断(IRQ

   128 0x80)          系统调用

   129~2380x81=0xee  外部中断(IRQ)

   239 (0XEF)            本地APIC时钟中断

   240-2500xf0~0xfa)    linux留做将来使用

   251~255(0xfb~0xff)    处理器间中断

 IRQ可配置设备选择一条线有三种方式

    1 设置一次些硬件跳线

    2 安装设置是执行一个实用程序

    3 在系统启动时执行一个硬件协议

  IRQ 的数据结构

   hw_irq_controller(); 驱动程序可见的中断源透明的链接到适当的控制器。

IRQ 在多处理器系统的分发

   在系统启动的过成中,引导cpu执行setup_IO_APIC_irqs()函数以初始化I/O APIC芯片。在系统启动期间,所有的cpu都执行setup_local_APIC()函数,该函数处理本地的APIC初始化。特别是 每个芯片的任务优先级寄存器(TPR)都初始化为一个固定值。

十: do_irq()的分析
do_irq(struct pt_regs *regs); 其中regs 用来访问irq_desc数组适当的元素。
1:获得自旋锁 2: 调用主IRQ描述符的ack方法做出应答。 3: 初始化主IRQ描述符的几个标志。 4: 调用handle_IRQ_event()处理中断。 5: 释放自旋锁  6: 返回。
irq_desc[irq].action 为NULL当中断没有相关的中断服务例程是出现这种情况
十一: 挽救丧失的中断
  在SMP系统中,enable_irq() 同过检查IRQ_PENDING标志来检测到一个中断被丢失的。由于在多核系统中cpu经常可能忽视一些中断,致使一些中断丢失,所以,此时挽救丧失的中断显得比较重要
十二: 中断服务例程
  handle_IRQ_event();
十三 : IRQ线的动态分布
   如果同一条IRQ线被几个硬件设备使用,及时这些设备不允许IRQ共享,要使这些设备的活动串行化,以便一次只能有一个设备拥有这个IRQ线。在激活一个设备利用IRQ线的设备之前,其相应的驱动程序调用request_irq()建立一个新的irqaction描述符,并初始化他。从而达到动态分布。
十四:处理器间的中断处理
    这里主要是介绍了一些函数,用来处理其之间的发送中断。
十五:软中断 tasklet 及 下半部分
   这里主要是讲述了可延迟中断,可延迟中断可以在开中断的情况下执行。把可延迟的中断抽出来是有助于是内核保持响应时间较短。对于一些紧急程序来说相当有必要
    做为一般性原则,同一个cpu上不能在中断一个软中断而去运行另一个软中断;同样的原则也适用于建立在软中断之上的tasklet和下半部分。
可延迟函数            动态分配   并发性
软中断                NO       可在几个cpu上并发执行
Tasklet              YES      不同类的可在cpu上并发执行   同类的不能在cpu上并发执行
下半部分              NO       不能在几个cpu之间并发运行
总之,可延迟函数必须逐次的执行。   可延迟函数可以执行四种操作: 初始化,激活, 屏蔽, 执行。 其中激活和执行总是捆绑在一起去执行。
软中断的执行
   open_softirq()函数处理软中断的初始化。检查软中断的挂起是在内核代码的几个点上进行的,在检查每个点时,内核读取solfirq_pending(cpu)如果这个字段不为空,内核就调用do_softirq()执行软中断。
十六: 软中断的内核线程
  每个cpu都有自己的ksoftirq_CPUn内核线程,都执行ksofitirq()函数。软中断可以重新激活自己;实际上,网路软中断和tasklet软中断都可以这么做。像网卡上的数据包泛滥这样的外部事件可能以高频率激活软中断。软中断的持续高流量可能会产生问题,这个问题就通过引入的内核线程来解决问题。
  当没有内核线程时,开发者有两种选择
  第一, 忽略do_softirq()运行时出现的软中断。
  第二, 不断重新检查挂起的软中断。do_softirq()一直检查挂起的软中断,只有没有挂起的软中断时才终止。不过这样可能使do_softirq()永远执行下去,用户态进程就停止执行。
   do_softirq()函数确定那些中断是挂起的,并执行他们。当执行的软中断又被激活时,do_softirq()唤醒ksofirq_CPUn内核线程并终止。内核线程有较低的优先级,用户程序就有可能执行。
十七:tasklet      
   是I/O驱动程序中可延迟函数的首选方法。
十八 :下半部分
  下半部分本质上说是一个不能与其他下半部分并发执行的高优先级的tasklet,即使它是一个不同的类型,并在另一个cpu上运行。
  引入可延迟函数的目的是,允许一些与中断处理相关的有限个函数以推迟的方法执行。
  1 :允许一个普通呃逆和函数,而不仅仅是服务与中断的一个函数,能以下半部分的身份运行。
  2: 允许几个内核函数,而不是单独的一个函数,能与一个下半部分相关联。
十九 : 从中断和异常的返回
   主要是讲了几个返回函数,和他们的过程。  
阅读(3545) | 评论(1) | 转发(1) |
0

上一篇:没有了

下一篇:C语言中的volatile关键字(转载)

给主人留下些什么吧!~~

chinaunix网友2010-09-13 12:53:19

按照ULK录入的吧。