计算机中的“中断”(Interruption),广义上理解,是指打断(interrupt)正在执行的程序使得处理器去执行其他程序。(BTW:“中断”一词,听上去莫名其妙,感觉叫“打断”更贴切,只不过有点难听。。。)
整个操作系统就是一个中断驱动的死循环,操作系统原理如果用一行代码解释,下面这样再合适不过了。
while(true) { doNothing(); }
其他所有事情都是由操作系统提前注册的中断机制和其对应的中断处理函数完成,我们点击一下鼠标,敲击一下键盘,执行一个程序,都是用中断的方式来通知操作系统帮我们处理这些事件,当没有任何中断事件时,它就乖乖停在死循环里不出来。
所以,中断,非常重要,它也是理解整个操作系统的根基。
Linux 操作系统中大多数设备都采用中断处理方式来控制数据 I/O 。
打断程序执行的方式
总结——硬中断和软中断
从中断实现的角度看,分为硬中断和软中断。
硬中断:由硬件CPU实现。
实现:CPU 在每个指令周期的最后,会留一个 CPU 周期去查看是否有中断信号,若有,则把中断号取出、去中断向量表中寻找中断处理程序、跳过去执行。
触发:外部硬件直接给CPU引脚发送中断号信息,从而引起中断。
分类:根据硬中断触发的方式的不同,硬中断可进一步分类:直接给CPU INTR引脚发信号触发中断、CPU自身执行指令触发中断、软件通过int n等指令触发中断。详见后文。
软中断:完全由软件实现。
实现:OS有一个单独的守护进程,不断轮询内存中的一组标志位(如BitMap),如果哪个标志位有值了,那去这个标志位对应的软中断向量表数组的相应位置,找到软中断处理函数,然后跳过去执行。
触发:其他软件通过设置这些标记位触发中断。
相关源码:
asmlinkage void __init start_kernel(void) { ... trap_init(); sched_init(); time_init(); ... rest_init(); } static void rest_init(void) { kernel_thread(init, NULL, CLONE_KERNEL); } static int init(void * unused) { do_pre_smp_initcalls(); } static void do_pre_smp_initcalls(void) { spawn_ksoftirqd(); } // spawn kernel soft irt daemon 创建内核软中断守护进程 __init int spawn_ksoftirqd(void) { cpu_callback(&cpu_nfb, CPU_ONLINE, (void *)(long)smp_processor_id()); register_cpu_notifier(&cpu_nfb); return 0; } static int __devinit cpu_callback(...) { kernel_thread(ksoftirqd, hcpu, CLONE_KERNEL); } static int ksoftirqd(void * __bind_cpu) { for (;;) { while (local_softirq_pending()) { do_softirq(); cond_resched(); } } } asmlinkage void do_softirq(void) { h = softirq_vec;//软中断列表首地址 pending = local_softirq_pending(); //软中断标记字,int 32类型 do { if (pending & 1) { h->action(h);//执行中断处理程序 h++; pending >>= 1; } while (pending); }