------------------- 中断注册 ---------------
中断的注册实质上就是对指定的中断线确定一个中断处理程序,注册时需要指定的有,中断线,中断处理函数,触发方式。 其他的参数都可以是null. 最后一个参数是名字,这个可以是null, 不过最好写上名字。 这个在/proc/inperupts 最后一列,就是这里指定的名字。如果是共享中断,就不能是null了, 要设定特定的标志,要设置设备id.
申请中断时,要查一下设备datasheeet的中断标志位,看是不是共享中断,即多个设备共享一个中断,如果是共享中断,在request_irq申请中断时,表示中断标志的第三个参数要设置为IRQ_HANDLED, 如果这个设置错了,内核在此就挂掉。
中断分为硬件中断,软件中断。硬件中断即芯片报过来的中断号,中断号即是原理图上看到的中断线。
Dbounce, 分为硬件方式和软件方式,因为信号都有波动,dounce指定当信号稳定时间到指定时间,才算中断发生。
----------------- 中断处理程序 -----------------------
中断处理函数返回值IRQ_HANDLED表示表示接收到的中断确实是指定的设备产生的中断,不是虚假中断 。 IRQ_none表示是虚假中断. 到目前接触的i2c, kpd, 都是直接返回IRQ_HANDLED。共享中断在红米 note上没使用。
为了确保中断处理程序不被抢占,即不让出cpu, 一般要禁用中断。因为中断可以qian套,就是一个中断处理程序被其他中断所打断,所以要禁用中断。禁用中断有两种,一是禁用所有中断,即local_irq_disable. 一是禁用特定中断线上的中断,用disable_irq_nosync. disable_irq是同步的,即中断处理程序执行结束后,这个中断函数才返回。 这个同步使cpu,不能响应其他事情,使整个系统崩馈。 所以disable_irq_nosync,不用等中断处理结束,就直接返回。
中断禁用前,要把中断的相关信息保存起来,(调用 local_irq_save)中断激活后,要中断相关信息要恢复成中断禁用前的信息( local_irq_restore)。
---------------- 中断上下文 ------------------
内核上下文, 即进程上下文,是应用进程通过系统调用而进入内核,这时内核代表当前进程,内核可通过current查询当前进程的信息,在内核上下文中可以睡眠。进程上下文包括cpu寄存器的值,进程的状态,堆栈里的数据。
中断上下文不属于进程的执行范围,不代表进程,在此环境中,看不到current及其信息,中断(严格说是上中断)意味着CPU不能做别的事情,直到上中断结束。
处在中断上下文的有中断处理程序,和执行下中断的tasklet. 中断上下文是不能睡眠的,即不能被抢占。 因为wake_up只能唤醒进程,而不能唤醒中断上下文的程序,这里的程序没有task_struct, 不属于进程的范畴。 中断上下文是不能被唤醒的。 凡是可能引起睡眠的函数都不能被中断处理程序调用。
中断处理程序使用的堆栈:内核所处的上下文只有两种,一是进程上下文,一是中断上下文。中断还有一层意思是,中断当前的进程。 中断上下文没有自己的堆栈,中断处理程序使用的栈,就是从被中断的进程的栈。进程的堆栈都在内核中。 如果没有进程运行,就用idle进程的中断。这个栈大小是固定的,在32位上是8KB, 在64位上是16KB。
---------------------- 下中断 -------------------
上中断做紧急的硬件写数据然后把下中断例程挂到下中断队列中,上中断时间是非常短的,在些期间,CPU不能响应其他中断,中断几乎所有的事情都交给下中断做,下中断的实现有工作队列或tasklet.
-------------- 查看中断相头信息 ---------------------
/proc/interrupts.
第一列是中断线(中断号),第二列是一个接收中断数目的计数器,第三列是处理这个中断的中断控制器,最后一列是与这个中断有关的设备名字,
--------------------- 内核抢占 --------------------------
内核抢占:关于抢占与非抢占命名,是指进程运行时,并且通过系统调用,在内核空间中运行时,这个时候,如果是非抢占的,那么内核想让进程让出cpu, 即调度进程进入睡眠,就必须等这个进程调这个系统调用结束后,才能进行进程调度。如果是抢占式的,就不必等系统调用结束,即可让当前进程让出cpu. 抢占的命名即是当前进程所用的cpu被其他进程给抢了。
就算内核是抢占式的,但有几个地方是不能抢占的,中断处理程序,tasklet,
linux之前是非抢占的,即进程让出cpu,
------------------- 内核对中断的实现 ----------------------
主要是do_irq 和 irq_handle_event两个函数。
linux 中断(原创)