日期:2014-05-16 浏览次数:20799 次
中断机制
对于 Linux 内核来说,中断信号通常分为两类:硬件中断和软件中断(异常)。每个中断是由 0-255
之间的一个数字来标识。对于中断 int0--int31(0x00--0x1f),每个中断的功能由 Intel 公司固定设定或保留
用, 属于软件中断,但 Intel 公司称之为异常。因为这些中断是在 CPU 执行指令时探测到异常情况而引
起的。通常还可分为故障(Fault)和陷阱(traps)两类。中断 int32--int255 (0x20--0xff)可以由用户自己设定。
在 Linux 系统中,则将 int32--int47(0x20--0x2f)对应于 8259A 中断控制芯片发出的硬件中断请求信号
IRQ0-IRQ15,并把程序编程发出的系统调用(system_call)中断设置为 int128(0x80)。
系统定时
在 Linux 内核中, PC机的可编程定时芯片 Intel 8253 被设置成每隔 10 毫秒就发出一个时钟中断
(IRQ0)信号。这个时间节拍就是系统运行的脉搏,我们称之为 1 个系统滴答。因此每经过 1 个滴答就
会调用一次时钟中断处理程序(timer_interrupt)。该处理程序主要用来通过 jiffies 变量来累计自系统启动
以来经过的时钟滴答数。每当发生一次时钟中断该值就增 1。然后从被中断程序的段选择符中取得当前
特权级 CPL 作为参数调用 do_timer()函数。
do_timer()函数则根据特权级对当前进程运行时间作累计。如果 CPL=0,则表示进程是运行在内核态
时被中断,因此把进程的内核运行时间统计值 stime 增 1,否则把进程用户态运行时间统计值增 1。如果
程序添加过定时器,则对定时器链表进行处理。若某个定时器时间到(递减后等于 0),则调用该定时器
的处理函数。然后对当前进程运行时间进行处理,把当前进程运行时间片减 1。如果此时当前进程时间
片并还大于 0,表示其时间片还没有用完,于是就退出 do_timer()继续运行当前进程。如果此时进程时间
片已经递减为 0,表示该进程已经用完了此次使用 CPU 的时间片,于是程序就会根据被中断程序的级别
来确定进一步处理的方法。若被中断的当前进程是工作在用户态的(特权级别大于 0),则 do_timer()就
会调用调度程序 schedule()切换到其它进程去运行。如果被中断的当前进程工作在内核态,
也即在内核程序中运行时被中断, do_timer()会立刻退出。因此这样的处理方式决定了 Linux 系统在内核态运行时不
会被调度程序切换。内核态程序是不可抢占的,但当处于用户态程序中运行时则是可以被抢占的。