Linux kernel 当中断发生时,内核如何处理进程上下文中的锁?

Linux kernel 当中断发生时,内核如何处理进程上下文中的锁?,linux-kernel,kernel,Linux Kernel,Kernel,首先,有点模棱两可,我很抱歉。。。我想了解的是下面的场景 假设Process正在运行,它持有一个锁,现在在获取锁之后,HW中断被生成,那么内核将如何处理这种情况,它会等待锁吗?如果是,那么如果中断处理程序需要访问该锁或受该锁定进程保护的共享数据,该怎么办?让我解释一下中断处理程序或下半部分的一些基本属性 处理程序不能向用户空间传输数据或从用户空间传输数据,因为它不在进程上下文中执行 处理程序也不能做任何会导致睡眠的事情,比如调用wait_事件、使用GFP_原子以外的任何东西分配内存,或者锁定信号

首先,有点模棱两可,我很抱歉。。。我想了解的是下面的场景


假设Process正在运行,它持有一个锁,现在在获取锁之后,HW中断被生成,那么内核将如何处理这种情况,它会等待锁吗?如果是,那么如果中断处理程序需要访问该锁或受该锁定进程保护的共享数据,该怎么办?

让我解释一下中断处理程序或下半部分的一些基本属性

  • 处理程序不能向用户空间传输数据或从用户空间传输数据,因为它不在进程上下文中执行
  • 处理程序也不能做任何会导致睡眠的事情,比如调用wait_事件、使用GFP_原子以外的任何东西分配内存,或者锁定信号量
  • 处理程序无法调用调度
  • 我想说的是,中断处理程序在原子上下文中运行。他们不能睡觉,因为他们不能重新安排时间。中断没有支持进程上下文

    以上是设计的。你可以在代码中做你想做的任何事情,只需为后果做好准备

    让我们假设您在中断处理程序中获得了一个锁(糟糕的设计)。 当中断发生时,进程将其寄存器保存在堆栈上并启动ISR。现在,在获得锁之后,您将处于死锁状态,因为他们的ISR不可能知道进程在做什么

    在使用ISR完成之前,流程将无法恢复执行


    在抢占式内核中,ISR和进程可以被抢占,但对于非抢占式内核,您就死定了。

    Linux内核有一些获取自旋锁的函数,用于处理您在这里提出的问题。特别是有
    spin\u lock\u irq()
    ,它禁用中断(在进程运行的CPU上)并获取spinlock。当代码知道在获取自旋锁之前已启用中断时,可以使用此选项;如果函数可能在不同的上下文中调用,还有
    spin\u lock\u irqsave()
    ,它在禁用中断之前隐藏中断的当前状态,以便通过
    spin\u unlock\u irqrestore()
    重新启用中断


    在任何情况下,如果在进程和中断上下文中都使用锁(如果上下文之间需要共享数据,这是一种很好且非常常见的设计),那么进程上下文在获取自旋锁时必须禁用中断(在其运行的CPU上本地),以避免死锁。事实上,lockdep(“CONFIG\u PROVE\u LOCKING”)将验证这一点,并在自旋锁的使用方式易受“进程上下文持有锁时中断”死锁的影响时发出警告。

    我想您可能会感到困惑。我问你是否在进程上下文中,然后中断来了,如果进程上下文持有一个锁,会发生什么……你用另一种方式解释了我。如果进程上下文持有一个锁,它只会被重新调度。这是当进程上下文持有锁时通常发生的情况。它不需要中断来重新调度它,内核将为其他进程自动重新检查它,除非它使用自旋锁。因此,在这种情况下,受锁保护的数据会发生什么情况,它不会处于不一致的状态?我们怎样才能克服这个问题……如果中断需要进程保存的数据,它将不得不等待,这就是死锁。这正是我在回答中所解释的。您能详细说明当中断被禁用时,当硬件请求处理时会发生什么情况吗?如果硬件在CPU已禁用中断时引发中断,那么中断将被挂起,直到CPU重新启用中断。当中断重新启用时,CPU将接受中断并输入其ISR,但在此之前,CPU将忽略挂起的中断。