嵌入式技术
中断信号的作用
由中断或异常处理程序执行的代码不是一个进程。而是一个内核控制路径,比一个进程的上下文要少,建立或终止需要的时间很少。为了应答中断,内核需要执行的活动分为两部分:上半部分(立即执行),下半部分(一个函数等待队列)
中断:
中断分为可屏蔽中断(清eflag寄存器的IF标志关闭中断)和不可屏蔽中断。
异常:
当CPU执行一条指令时所探测到的一个反常条件所产生的异常。这取决于CPU控制单元产生异常时保存在内核态堆栈eip寄存器的值:
故障:保存在eip中的值是引起故障的指令地址,当异常处理程序终止时, 会重新执行那条指令。
陷阱:该指令在引起陷阱的指令地址后。只有当没有必要重新执行已执行过的指令时,才触发陷阱。其主要用途是为了调试程序。
异常结束:发生严重错误,迫使程序异常终止。
编程异常:在编程者发出请求时发生。
中断和异常向量
每个中断和异常是由0~255之间的一个数来标识。因为一些未知原因,Intel把这个8位的无符号整数叫做一个向量。不可屏蔽中断的向量和异常的向量都是固定的(0~31),而可屏蔽中断的向量(32~47 IRQ)可以通过对中断控制器的编程来改变。
其中,48~255的向量用来标识软中断(即编程异常)。Linux只用了一个,即128,用来实现系统调用。当用户态下的进程执行一条int 0x80汇编指令时,CPU切换到内核态,并开始执行system_call()函数。
IRQ和中断
每个能够发出中断请求的硬件设备控制器都有一个指派为IRQ(Interrupt ReQuest)的输出线。所有现有的IRQ线都与一个叫做中断控制器的硬件电路的输入引脚相连。
硬件设备控制器发出信号给中断控制器,中断控制器接受信号后转换成对应向量,CPU可以读这个向量并确认后,清INTR线。
IRQ按顺序编号,与向量之间的映射可以通过向中断控制器端口发布合适的指令来修改。IRQ线可以被复用,也可以被启用/禁用,禁用时,eflags寄存器的IF标志被清除。
中断描述符表
中断描述符表(IDT)是一个系统表,它与每一个中断或异常向量相联系,每一个向量(8字节)有相应的中断或异常处理程序的入口地址。在内核允许中断发生前,必须适当地初始化IDT。
表中每一项对应一个中断或异常向量,,idtr寄存器允许IDT位于内存任何地方,它指定了IDT的物理基地址及其限制。
IDT包含了三种类型的描述符,任务门,中断门,陷阱门。其中,中断门包含了段选择符和一个中断或异常处理程序的段内偏移量。当控制器转移到合适的段时,处理器清IF标志,从而关闭接下来会发生的可屏蔽中断。
Linux利用中断门处理中断,利用陷阱门处理异常。
那么怎么处理中断或异常呢?
中断或异常向量i----->IDTR寄存器找到IDT表第i项------>从gdtr寄存器获得GDT基地址并利用IDT表中的段选择符和偏移量查找中断或异常处理程序所在的段的基地址------->安全检查(CPL==DPL)
中断和异常处理程序的嵌套执行
当CPU正在执行一个与中断有关的内核控制路径时,Linux的设计不允许发生进程切换。但是,这样的内核控制路径可以随意的嵌套,即一个中断处理程序可以由另一个中断处理程序进行中断,如此等等。当然,异常处理程序也可以被推迟。
初始化中断描述符表
首先,在初始化前,需要将IDT表的初始地址装到idtr寄存器,并初始化表中的每一项,在Linux中,没有任务门一说,倒有叫做系统门。IDT通常会被初始化两次,BIOS例程位第一次。
最后几个问题
内核控制路径并发执行的数量:如果仅仅只有一个,那么CPU必须切换到用户态。
激活的,等待被执行的下半部分:如果有一些,必须执行它们。
如果有任何请求,内核就必须执行进程调度;否则,把控制权还给当前进程。
如果信号已经发送到当前进程,就必须处理它。
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !