From: Felix Lee Date: Wed, 20 Sep 2023 22:28:00 +0000 (+0800) Subject: revised chapter interrupt all parts X-Git-Url: https://www.ivnss.com/gitweb/?a=commitdiff_plain;h=7def6f5a8497b205b37a90046259828f139a9f7b;p=lkmpgcn revised chapter interrupt all parts --- diff --git a/lkmpg_cn.tex b/lkmpg_cn.tex index 50e60d1..2fb8a7d 100644 --- a/lkmpg_cn.tex +++ b/lkmpg_cn.tex @@ -2039,39 +2039,38 @@ Completely Fair Scheduler 缩写为 CFS\,)\,来执行队列中的工作。 读取其信息,那么这些信息就会丢失。 在 Linux 下,硬件中断被称为 IRQ (Interrupt ReQuests)。IRQ 有两种类型,短的与长% -的。一个短的 IRQ 是一种预计需要很短时间 IRQ,在此期间机器的其余部分将被阻塞并% -且不会处理其它中断。长 IRQ 可能需要更长的时间,并且在此期间可能会发生其它中断(% -但不是来自同一设备的中断)。如果可能的话,最好将中断处理程序声明的较长。 - -当 CPU 收到一个中断时,它会停止正在做的任何事情(除非它正在处理一个更重要的中断,% -在这种情况下,只有当更重要的中断完成时,它才会处理这个中断)。将某些参数保存在堆% -栈上并调用中断处理程序。这意味着中断处理程序本身不允许执行某些操作,因为系统处% -于未知状态。Linux 内核通过将中断处理分为两部分来解决这个问题。第一部分立即执行% -并屏蔽中断线,硬件中断必须快速处理,这就是为什么我们需要第二部分来处理繁重的工% -作,并从中断处理中延后执行。历史上,BH (Linux 称为 \textit{Bottom Halves})以统% -计方式记录延迟函数。\textbf{Softirq} 与它的高级抽象,\textbf{Tasklet},从 Linux % -2.3 开始替换 BH。 - -实现的方法是,当有关的 IRQ 被收到时,使用 \cpp|request_irq()| 得到你的中断处理% -被调用。 - -在实践中,IRQ 处理可能是有此复杂。硬件通常以链接两个中断控制器的方式被设计,以% +的。一个短的 IRQ 是一种预计需要很短的时间 IRQ,在此期间机器的其余部分指令将被% +阻塞并且不会处理其它中断。长 IRQ 可能需要更长的时间,并且在此期间可能会发生其% +它中断\,(\,但不是来自同一设备的中断\,)。如果可能的话,最好将中断处理程序声明% +为长中断类型。 + +当 CPU 收到一个中断时,它会停止正在做的任何事情\,(\,除非它正在处理一个更重要% +的中断,在这种情况下,只有当更重要的中断完成时,它才会处理这个中断)。将某些参% +数保存在堆栈上并调用中断处理程序。这意味着中断处理程序本身不允许执行某些操作,% +因为系统处于未知状态。Linux 内核通过将中断处理分为两部分来解决这个问题。第一部% +分立即执行并屏蔽中断线,硬件中断必须快速处理,这就是为什么我们需要第二部分来处% +理繁重的工作,并从中断处理中延后执行。历史上,BH (\,Linux 称为 \textit{Bottom Halves\/}\,)\,% +以统计方式记录延迟函数。\textbf{Softirq} 与它的高级抽象,\textbf{Tasklet},从 % +Linux 2.3 开始替换 BH。 + +实现的方法是,当有关的 IRQ 被收到时,使用 \cpp|request_irq()| 得到你被调用的% +中断处理例程。 + +在实践中,IRQ 处理可能是有些复杂。硬件通常以链接两个中断控制器的方式被设计,以% 便来自中断控制器 B 的所有 IRQ 都级联到中断控制器 A 的某个 IRQ。当然,这需要内核% 随后找出它到底是哪个 IRQ,这会增加额外的开销。其它架构提供一些特殊的,非常低的% -开销,所谓的``快速IRQ''或 FIQ,要利用它们,需要用汇编语方编写处理程序,因此它% -们并不真正融入内核。 - -可以使它们与其它 IRQ 类似地工作,但在该过程之后,它们不再比``常见'' IRQ 更快。% -在具有多个处理器的系统上运行的支持 SMP 的内核需要解决一大堆问题。仅仅知道某个 % -IRQ 是否发生是不够的,了解它是针对哪个 CPU 也很重要。人们仍然对更多细节感兴趣,% -现在可能想参考``APIC''。 +开销,所谓的\,``快速IRQ''\,或 FIQ,要利用它们,需要用汇编语言编写处理程序,因此% +它们并不真正融入内核。可以使它们与其它 IRQ 类似地工作,但在该过程之后,它们不% +再比``常见'' IRQ 更快。在具有多个处理器的系统上运行的支持 SMP 的内核需要解决一% +大堆问题。仅仅知道某个 IRQ 是否发生是不够的,了解它是针对哪个 CPU 也很重要。人% +们仍然对更多细节感兴趣话,现在可能想参考``APIC''。 这个函数接收 IRQ 数字,该函数的名字,标记,为 \verb|/proc/interrupts| 设定的名% 称与一个被传递到中断控制处理程序的参数。通常这里有一定数量的 IRQ 可用。有多少 % -IRQ 是依赖于硬件的。标记可以包括 \cpp|SA_SHIRQ| 来指示你将与其它中断处理程序(% -通常是因为许多硬件设备位于同一个 IRQ 上)共享 IRQ,并且 \cpp|SA_INTERRUPT| 来指% -明这是一个快速中断。仅当此 IRQ 上尚无处理程序或双方都愿意共享时,此函数才会成功。 - +IRQ 是依赖于硬件的。标记可以包括 \cpp|SA_SHIRQ| 来指示你将与其它中断处理程序\,(\,% +通常是因为许多硬件设备位于同一个 IRQ 上\,)\,共享 IRQ,并且 \cpp|SA_INTERRUPT| % +来指明这是一个快速中断。仅当此 IRQ 上尚无处理程序或双方都愿意共享时,此函数才% +会成功。 \section{探测按钮按下} \label{sec:detect_button} @@ -2080,15 +2079,16 @@ IRQ 是依赖于硬件的。标记可以包括 \cpp|SA_SHIRQ| 来指示你将与 要使用中断,因此,与其让 CPU 浪费时间和电池电量来轮询输入状态的变化,不如让输入% 触发 CPU 然后运行特定的处理函数。 -这里是一个示例,在这里按钮被连接到 GPIO 数字 17 与 18,并且一个 LED 被连接到 % -GPIO 4。你可以为你的单板机修改合适的引脚数字。 +这里是一个示例,在这里按钮被连接到 GPIO 编号 17 与 18,并且一个 LED 被连接到 % +GPIO 编号\,4。你可以根据你的单板机修改合适的引脚编号。 \samplec{examples/intrpt.c} \section{底半部分} \label{sec:bottom_half} -假设你想在中断例程内执行一系列操作。在不使中断长时间不可用的情况下,实现此目的% -的一种常见方法是将其与一个 tasklet 联系起来。这将大部分工作推入调度程序。 +假设你想在中断例程内执行一系列操作。一种常见的实现方法,且此方法不会因处理任务% +时间太长,而招致中断不可用时,是采用与一个 tasklet 组合使用来解决问题。这将大% +部分工作推给调度器例程。 下面的示例修改了前面的示例,以便于在触发中断时也运行附加任务。