《第五章-中断与异常-《Linux操作系统原理与应用》电子教案课件.ppt》由会员分享,可在线阅读,更多相关《第五章-中断与异常-《Linux操作系统原理与应用》电子教案课件.ppt(37页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第五章第五章 中断与异常中断与异常中断的基本知识中断描述符表的初始化中断处理中断的下半部处理机制中断的应用时钟中断中断控制的主要优点:中断控制的主要优点:CPU只有在只有在I/O需要服务时才响应需要服务时才响应外部中断:外部中断:外部设备所发出的外部设备所发出的I/O请求请求内部中断:内部中断:也称之为也称之为“异常异常”,是为解决机器运,是为解决机器运行时所出现的某些随机事件及编程方行时所出现的某些随机事件及编程方便而出现的便而出现的中断掠影中断掠影中断向量中断向量:中断源的编号外设可屏蔽中断:外设可屏蔽中断:屏蔽外部I/O请求 异常及非屏蔽中断异常及非屏蔽中断:CPU内部中断或计算机内部硬
2、件出错引起的异常中断描述符表中断描述符表:描述中断的相关信息中断相关的汇编指令中断相关的汇编指令:中断常识中断常识中断向量中断向量每个中断源都被分配一个8位无符号整数作为类型码,即中断向量中断的种类:中断的种类:中断:外部可屏蔽中断外部非屏蔽中断异常:不使用中断控制器,不能被屏蔽故障陷阱中断向量中断源的类型中断向量中断源的类型 异常就是CPU内部出现的中断,即在CPU执行特定指令时出现的非法情况。非屏蔽中断就是计算机内部硬件出错时引起的异常情况 Intel把非屏蔽中断作为一种异常来处理在CPU执行一个异常处理程序时,就不再为其他异常或可屏蔽中断请求服务 异常及非屏蔽中断 中断描述符表(中断描述
3、符表(IDT):即中断向量表,):即中断向量表,每个中断占据一个表项每个中断占据一个表项中断描述符表中断描述符表调用过程指令CALL:CALL 过程名过程名调用中断过程的指令INT INT 中断向量中断向量 中断返回指令IRETIRET 加载中断描述符表的指令LIDT LIDT 48位的位的伪伪描述符描述符 相关汇编指令相关汇编指令 IDT表项的设置通过_set_gaet()函数实现 调用该函数在IDT表中插入一个中断门:set_intr_gate(unsigned int n,void*addr)调用该函数在IDT表中插入一个陷阱门:set_trap_gate(unsigned int n,
4、void*addr)调用该函数在IDT表中插入一个系统门:set_system_gate(unsigned int n,void*addr)IDT表项的设置表项的设置trap_init()函数用于设置中断描述符表开头的19个陷阱门和系统门这些中断向量都是CPU保留用于异常处理的,例:set_trap_gate(0,÷_error);set_trap_gate(1,&debug);set_trap_gate(19,&simd_coprocessor_error);set_system_gate(SYSCALL_VECTOR,&system_call);初始化陷阱门和系统门初始化陷阱门
5、和系统门中断和异常的硬件处理:从硬件的角度看从硬件的角度看CPU如何处理中断和异常如何处理中断和异常中断请求队列的建立:方便外设共享中断线方便外设共享中断线 中断处理程序的执行 从中断返回:调调用用恢恢复复中中断断现现场场的的宏宏RESTORE_ALL,彻底从中断返回彻底从中断返回 中断处理中断处理 确定所发生中断或异常的向量i(在0255之间)通过IDTR寄存器找到IDT表,读取IDT表第i项(或叫第i个门)分“段”级、“门”级两步进行有效性检查 检查是否发生了特权级的变化 中断和异常处理中中断和异常处理中CPUCPU的工作的工作SSESPEFLAGSCSEIPERROR CODEEFLAG
6、SCSEIPERROR CODE堆栈增长方向中断发生前夕的SS:ESP返回地址错误码中断处理程序堆栈由于硬件条件的限制,很多硬件设备共享一条中断线为方便处理,Linux为每条中断线设置了一个中断请求队列中断服务例程与中断处理程序中断线共享的数据结构注册中断服务例程中断请求队列的建立中断请求队列的建立struct irqaction void(*handler)(int,void*,struct pt_regs*);unsigned long flags;unsigned long mask;const char*name;void*dev_id;struct irqaction*next;Ha
7、ndler:指向一个具体I/O设备的中断服务例程Flags:用一组标志描述中断线与I/O设备之间的关系。SA_INTERRUPT:中断处理程序执行时必须禁止中断SA_SHIRQ:允许其它设备共享这条中断线。中断线共享的数据结构中断线共享的数据结构 struct irqaction void(*handler)(int,void*,struct pt_regs*);unsigned long flags;unsigned long mask;const char*name;void*dev_id;struct irqaction*next;SA_SAMPLE_RANDOMSA_SAMPLE_RA
8、NDOM:内核可以用它做随机数产生器。SA_PROBESA_PROBE:内核正在使用这条中断线进行硬件设备探测。NameName:I/O设备名dev_iddev_id:指定I/O设备的主设备号和次设备号(参见第9章)。NextNext:指向irqaction描述符链表的下一个元素 中断线共享的数据结构中断线共享的数据结构 初始化IDT表之后,必须通过 request_irq()函数将相应的中断服务例程挂入中断请求队列,即对其进行注册 在关闭设备时,必须通过调用free_irq()函数释放所申请的中断请求号 注册中断服务例程注册中断服务例程 int request_irq(unsigned in
9、t irq,void(*handler)(int,void*,struct pt_regs*),unsigned long irqflags,const char*devname,void*dev_id)CPU从中断控制器的一个端口取得中断向量I 根据I从中断描述符表IDT中找到相应的中断门从中断门获得中断处理程序的入口地址 判断是否要进行堆栈切换调用do_IRQ()对所接收的中断进行应答,并禁止这条中断线调用handle_IRQ_event()来运行对应的中断服务例程 中断处理程序的执行中断处理程序的执行 当处理所有外设中断请求的函数do_IRQ()执行时,内核栈顶包含的就是do_IRQ()
10、的返回地址,这个地址指向ret_from_intr 从中断返回时,CPU要调用恢复中断现场的宏RESTORE_ALL,彻底从中断返回。从中断返回从中断返回 小任务是指待处理的下半部,其数据结构为tasklet_struct,每个结构代表一个独立的小任务 小任务既可以静态地创建,也可以动态地创建 小任务机制小任务机制 struct tasklet_struct Struct tasklet_struct*next;unsigned long state;atomic_t count;void(*func)(unsigned long);unsigned long data;;void taskl
11、et_handler(unsigned long data)小任务不能睡眠,不能在小任务中使用信号量或者其它产生阻塞的函数。但它运行时可以响应中断 通过调用tasklet_schedule()函数并传递给它相应的tasklet_struct指针,该小任务就会被调度以便适当的时候执行:tasklet_schedule(&my_tasklet)在小任务被调度以后,只要有机会它就会尽可能早的运行 编写并调度自己的小任务编写并调度自己的小任务下半部是一个不能与其他下半部并发执行的高优先级小任务 bh_base是一个指向下半部的指针数组,用于组织所有下半部 bh_base数组共有32项,每一项都是一种下
12、半部下半部下半部 下半部外部设备TIMER_BH 定时器TQUEUE_BH 周期性任务队列SERIAL_BH 串行端口IMMEDIATE_BH 立即任务队列Linux常用的下半部大部分PC机中有两个时钟源,分别是实时实时时钟(时钟(RTCRTC)和和 操作系统(操作系统(OSOS)时钟)时钟实时时钟也叫硬件时钟,它靠电池供电,即使系统断电,也可以维持日期和时间。RTC和OS时钟之间的关系通常也被称作操作系统的时钟运作机制 不同的操作系统,其时钟运作机制也不同 中断的应用时钟中断中断的应用时钟中断 时钟运作机制每一次时钟中断的产生都触发下列几个每一次时钟中断的产生都触发下列几个主要的操作:主要的
13、操作:自系统启动以来所花费的时间自系统启动以来所花费的时间更新时间和日期更新时间和日期确定当前进程在确定当前进程在CPU 上已运行了多长时间,上已运行了多长时间,如果已经超过了分配给它的时间,则抢占它如果已经超过了分配给它的时间,则抢占它更新资源使用统计数更新资源使用统计数检查定时器时间间隔是否已到,如果是,则检查定时器时间间隔是否已到,如果是,则调用适当的函数调用适当的函数 时钟中断处理程序时钟中断处理程序 timer_bh()函数与TIMER_BH 下半部相关联,它在每个时钟节拍都被激活 TIMER_BH 下半部以关中断调用update_times()函数,该函数会以关中断来更新xtime
14、 更新了系统时钟xtime之后,update_times()再次打开中断时钟中断的下半部处理时钟中断的下半部处理 定时器是管理内核所花时间的基础,也被称为动态定时器或内核定时器 定时器的使用:执行一些初始化工作,设置一个到期时间,指定到时后执行的函数,然后激活定时器就可以了定时器由timer_list结构表示 定时器及应用定时器及应用 struct timer_list struct list_head entry;unsigned long expires;unsigned long data;void(*function)(unsigned long);定义定时器:struct timer
15、_list my_timer;初始化定时器:init_timer(&my_timer);激活定时器:add_timer(&my_timer);如果需要在定时器到期前停止定时器,可以使用del_timer()函数:del_timer(&my_timer);定时器的使用定时器的使用内核在时钟中断发生后执行定时器,定时器在下半部中被run_timer_list()执行 定时器的使用:例:创建和使用进程延时定时器的执行与应用定时器的执行与应用timeout=2*HZ;/*1HZ等于100,因此为2000ms*/set_current_state(TASK_INTERRUPTIBLE);remainin
16、g=schedule_timeout(timeout);内核用定时器实现进程的延时,调用schedule_timeout()函数,该函数执行下列语句:struct timer_list timer;expire=timeout+jiffies;init_timer(&timer);timer.expires=expire;timer.data=(unsigned long)current;timer.function=process_timeout;add_timer(&timer);schedule();/*进程被挂起直到定时器到期*/del_timer_sync(&timer);timeo
17、ut=expire-jiffies;return(timeout 0?0:timeout);当延时到期时,内核执行下列函数:void process_timeout(unsigned long data)struct task_struct*p=(struct task_struct*)data;wake_up_process(p);“内核之旅内核之旅”网站网站电子杂志栏目是关于内核研究和学习的资料电子杂志栏目是关于内核研究和学习的资料 第八期第八期“中断中断”,将向读者依次解释中断概念,将向读者依次解释中断概念,解析解析LinuxLinux中的中断实现机理以及中的中断实现机理以及LinuxLinux下中断下中断如何被使用如何被使用。