【问题标题】:Page fault in Interrupt context中断上下文中的页面错误
【发布时间】:2011-01-31 07:16:02
【问题描述】:

在中断处理程序/原子上下文中会发生页面错误吗?

【问题讨论】:

  • 这对于 audio 驱动程序和其他使用 mmap 数据源的驱动程序很常见。页面错误处理程序中有特定的代码来关注之前的 IRQ 状态。任何copy_from_user()copy_to_user() 都可能出错。内核代码本身是pinned,所以只有data abortsdata faults应该发生。

标签: linux operating-system linux-kernel


【解决方案1】:

可以,但那将是一场灾难。 :-)

【讨论】:

  • @Bandicoot:相信这家伙,他是 Linux 内核开发人员。
  • @ninjalj:如果答案有帮助,就会更容易信任。
  • 发生页面错误 e. G。当被访问的虚拟地址映射到不存在的页面时。在中断上下文中,这意味着内核错误,并且与进程被终止的用户空间访问不同,终止中断处理程序是一种疯狂的选择,很有可能使硬件处于未定义状态。因此,内核崩溃,cpu 被锁定,需要重新启动
【解决方案2】:

(这是一个古老的问题。现有答案包含正确的事实,但很薄。我将尝试以更实质性的方式回答它。)

这个问题的答案取决于代码是在内核(管理员模式)还是在用户模式。原因是这些区域的内存访问规则通常不同。下面是一个简短的事件序列来说明问题(假设内核内存可以被分页):

  1. 在执行用户程序时,会发生中断(例如按键/磁盘事件)。
  2. CPU 转换到主管模式并开始执行内核中的处理程序。
  3. 中断处理程序开始保存 CPU 状态(以便以后可以正确恢复用户进程),但这样做会触及之前已被调出的部分存储空间。
  4. 这会触发页面错误异常。
  5. 为了处理缺页异常,内核现在必须保存发生缺页的代码的 CPU 状态。
  6. 如果它有一个永远不会被调出的预分配内存池,它实际上可能能够做到这一点,但这样一个池的大小将不可避免地受到限制。

如您所见,最安全(也是最简单)的解决方案是让内核确保内核拥有的内存根本不可分页。出于这个原因,页面错误不应该真正发生在内核中。它们可能会发生,但正如@adobriyan 指出的那样,这通常表明比简单地需要在某些内存中分页的错误要大得多。 (我相信 Linux 中就是这种情况。检查您的特定操作系统以确定内核内存是否不可分页。操作系统架构确实不同。)

因此,总而言之,内核内存通常是不可分页的,而且由于中断通常在内核中处理,因此在处理中断时通常不会发生页面错误。较高优先级的中断仍然可以中断较低优先级的中断。只是他们所有的资源都保存在物理内存中。

关于原子上下文的问题不太清楚。如果您的意思是硬件支持的原子操作,那么在操作的部分完成内不会发生中断。如果您指的是诸如临界区之类的东西,请记住临界区仅模拟原子性。从硬件的角度来看,这样的代码没有什么特别之处,除了入口和出口代码,它可能使用真正的硬件原子操作。中间的代码是普通代码,可能会被打断。

我希望这可以对这个问题提供有用的回答,因为我也想知道这个问题一段时间。

【讨论】:

  • 我认为例如,bitset 代码应该是原子的。在没有原子原语的平台上使用中断掩码访问时,这些数组可能会导致 页面错误
  • Linux内核内存不可分页,但通过vmalloc分配的内存仍然会导致页面错误,因此如果在中断中使用vmalloced内存可能会导致页面错误。
【解决方案3】:

是的。

处理程序或关键区域的代码可以跨越两个页面之间的边界。如果第二页不可用,则需要页面错误才能将其引入。

【讨论】:

  • 但是在中断/原子上下文中不允许休眠。并且调用页面错误处理程序可能会导致进程休眠。那么在中断上下文中允许页面错误不会导致死锁吗?
  • Linux 内核因此不可交换。 :)
【解决方案4】:

不知道为什么没有人使用“双重错误”这个词:

http://en.wikipedia.org/wiki/Double_fault

但这是英特尔手册中使用的术语:

http://software.intel.com/en-us/articles/introduction-to-pc-architecture/

或这里:

ftp://download.intel.com/design/processor/manuals/253668.pdf(参见第 6-38 节)。

还有一种叫做三重故障的东西,顾名思义,也可能发生在 CPU 尝试处理双重故障错误时。

【讨论】:

    【解决方案5】:

    我认为答案是肯定的。 我刚刚检查了内核 4.15 中用于 x86_64 平台的页面错误处理程序代码。 以以下为提示。 no_context 是经典的“内核糟糕”。

    no_context(struct pt_regs *regs, unsigned long error_code,
               unsigned long address, int signal, int si_code)
    {
    
            /* Are we prepared to handle this kernel fault? */
            if (fixup_exception(regs, X86_TRAP_PF)) {
                    /*
                     * Any interrupt that takes a fault gets the fixup. This makes
                     * the below recursive fault logic only apply to a faults from
                     * task context.
                     */
                    if (in_interrupt())
                            return;
    

    【讨论】:

      猜你喜欢
      • 2011-04-18
      • 1970-01-01
      • 2017-09-13
      • 1970-01-01
      • 2020-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多