5,中断和异常
中断,一般是外部事件引起,异步
异常,一般由软件产生,同步,如int n
陷阱,一般由软件产生,异步,如除0
通过中断门进入中断服务程序时,cpu会自动将中断关闭,也就是将EFLAGS中IF标志清0,防止嵌套中断的发生。而通过陷阱门进入中断服务程序时则IF不变。
do_IRQ()
do_IRQ之前
gcc预编译生成公用中断请求的服务程序,把中断号入栈,调用common_interrupt,
common_interrupt调用SAVEALL,保存寄存器的内容,把rt_from_intr入栈,调用do_IRQ
do_IRQ
依次调用中断线上注册的中断程序,所以中断程序要有检查机制,确定是否是自己的设备产生的中断,并ack
do_IRQ之后
ret_from_intr,内核检查保存的CS寄存器的最低2位,判断中断发生在用户空间还是内核空间,如果是用户空间,ret_with_reschedule,检查need_resched判断是否需要调度,是否有信号等待,如果是内核空间restore_all,恢复寄存器的内容,iret从中断返回。还应该包括内核的抢占和bh的处理部分
request_irq()
分配irq_action结构,初始化,注册。这个函数会调用kmalloc(),可能引起睡眠。
SA_INTERRUPT标志,中断分为快速中断和慢速中断,快速中断在屏蔽所有中断的前提下运行,使他们能尽快的执行的完,一般只有时钟中断使用这个标志。
如果没有设置这个标志,只有中断处理程序对应的中断线是被屏蔽的,具体的实现是在do_IRQ中实现的。
中断处理函数的返回值,
2.4内核中,返回void
2.6内核中,返回IRQ_NONE或IRQ_HANDLED。如果设备驱动程序被正确调用,并且正是对应的设备产生的中断,返回IRQ_HANDLED,否则返回IRQ_NONE.内核根据这些返回信息判断中断是否得到了正确的响应。
bh:
软中断,tasklet,workqueue
软中断: 1、软中断是在编译期间静态分配的。
2、最多可以有32个软中断。
3、软中断不会抢占另外一个软中断,唯一可以抢占软中断的是中断处理程序。
4、可以并发运行在多个CPU上(即使同一类型的也可以)。所以软中断必须设计为可重入的函数(允许多个CPU同时操作),
因此也需要使用自旋锁来保护其数据结构。
5、目前只有两个子系直接使用软中断:网络和SCSI。
6、执行时间有:从硬件中断代码返回时、在ksoftirqd内核线程中和某些显示检查并执行软中断的代码中。
tasklet: 1、tasklet是使用两类软中断实现的:HI_SOFTIRQ和TASKLET_SOFTIRQ。
2、可以动态增加减少,没有数量限制。
3、同一类tasklet不能并发执行。
4、不同类型可以并发执行。
5、大部分情况使用tasklet。
工作队列: 1、由内核线程去执行,换句话说总在进程上下文执行。
2、可以睡眠,阻塞。
系统的脉搏time_interrupt
17 static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
18 {
19 do_timer(regs);
20 do_set_rtc();
21 do_profile(regs);
22 }
674 void do_timer(struct pt_regs *regs)
675 {
676 (*(unsigned long *)&jiffies)++;
682 mark_bh(TIMER_BH);
683 if (TQ_ACTIVE(tq_timer))
684 mark_bh(TQUEUE_BH);
685 }
其中在sched_init中
1260 init_bh(TIMER_BH, timer_bh);
1261 init_bh(TQUEUE_BH, tqueue_bh);
timer_bh 内核定时器
tqueue_bh 运行tq_timer这个任务队列中的任务
软中断的调度时机:
1,中断代码返回
2,ksoftirqd内核线程中
3,显式检查和执行待处理的软中断代码中,如网络子系统
不管通过什么方法,软中断都通过do_softirq()执行
pending = softirq_pending(cpu);
if(pending)
{
sruct softirq_action *h = softirq_vec ;
soft_irq_pending(cpu) = 0;
do{
if(pending &1)
h->action;
h++;
pending >>=1;
}while(pending)
}
阅读(1488) | 评论(2) | 转发(0) |