Linux kernel 为什么我们需要中断上下文?
我有疑问,为什么我们需要中断上下文?一切都告诉我们什么是属性,但没有人解释我们为什么提出这个概念Linux kernel 为什么我们需要中断上下文?,linux-kernel,kernel,interrupt-handling,Linux Kernel,Kernel,Interrupt Handling,我有疑问,为什么我们需要中断上下文?一切都告诉我们什么是属性,但没有人解释我们为什么提出这个概念 与同一概念相关的另一个疑问是,如果我们不在中断处理程序中禁用中断,那么在中断上下文中运行此中断处理程序代码有什么用?中断上下文与进程上下文有根本不同: 它与过程无关;特定进程不提供中断服务,内核提供。即使进程将被中断,它对中断本身或为其服务的例程的任何参数都没有意义。因此,中断上下文至少在概念上必须不同于进程上下文 另外,如果一个中断在一个进程上下文中被服务,并且(重新)在以后的时间安排一些工作,那
与同一概念相关的另一个疑问是,如果我们不在中断处理程序中禁用中断,那么在中断上下文中运行此中断处理程序代码有什么用?中断上下文与进程上下文有根本不同:
ps
)和每个进程的VM(虚拟内存)上下文。VM对用户和内核模式具有不同的权限。为了使内核始终运行,它必须为设备上的所有进程保持映射。内核线程是一种特殊情况,它不太关心VM,因为它具有特权,可以访问所有内核内存。但是,它有一个单独的堆栈和进程上下文。发生异常时,用户寄存器通常存储在内核堆栈上。例外情况至少包括页面错误、系统调用和中断。这些项目可能会嵌套。也就是说,您可以从用户空间调用write()
,当内核传输用户缓冲区时,读取一些交换的用户空间数据可能会出现页面错误。页面错误可能再次需要为中断提供服务
中断递归
Linux general希望您将中断屏蔽为VM,执行和进程管理(上下文和上下文切换)必须协同工作。为了使VM保持简单,内核堆栈和进程上下文通常根于单个4k(或8k)区域,该区域是单个VM页面。始终映射此页面。通常,在为中断提供服务时,所有CPU都将从中断模式切换到系统模式,并使用与所有其他异常相同的内核堆栈。堆栈很小,因此允许递归(以及较大的堆栈分配)可能会炸毁堆栈,从而导致内核级别的堆栈溢出。这很糟糕
原子性
许多内核结构需要在多个总线周期内保持一致;也就是说,添加元素时,链表必须同时更新prev
和next
节点链接。这样做的典型机制可能是屏蔽中断,以确保代码是原子的。某些CPU可能允许总线锁定,但这不是通用的。上下文切换代码也必须是原子的。中断的结果通常是重新调度。也就是说,内核中断处理程序可能已确认磁盘控制器并开始写入操作。然后内核线程可以计划从原始用户空间写入更多缓冲数据write()
任何时候发生的中断都可能打破某些子系统对原子行为的假设。禁止他们使用子系统,而不是允许中断使用子系统
总结
Linux必须处理三件事。当前进程执行上下文、当前虚拟内存布局和硬件请求。他们都需要共同努力。由于中断可能随时发生,因此它们发生在任何流程上下文中。在中断中使用sleep()。允许在中断中分配大堆栈可能会破坏有限的堆栈。这些设计选择限制了Linux中断处理程序中可能发生的情况。各种配置选项可以允许重入中断,但这通常是特定于CPU的
保持上半部分(现在的主中断处理程序)较小的好处是减少了中断延迟。繁忙的工作应该在内核线程中完成。一种中断服务程序