我以前一直以为 Linux 内核之所以不允许在中断中休眠是因为中断上下文中无法获取 thread_info,task_struct 等进程相关的结构体,从而无法调度。 今天又重新看了一下相关的代码,发现实际上不是。在最新的代码中,x86 32 使用的 irq stack 中也保存了thread_info,我们可以看 execute_on_irq_stack() 的定义: [c] union irqctx { struct threadinfo tinfo; u32 stack[THREAD_SIZE/sizeof(u32)]; } __attribute((aligned(THREAD_SIZE))); static inline int execute_on_irq_stack(int overflow, struct irq_desc desc, int irq) { union irq_ctx curctx, irqctx; u32 isp, arg1, arg2; curctx = (union irq_ctx *) current_thread_info(); irqctx = __this_cpu_read(hardirq_ctx);
/* * this is where we switch to the IRQ stack. However, if we are * already using the IRQ stack (because we interrupted a hardirq * handler) we can't do that and just have to keep using the * current stack (which is the irq stack already after all) */ if (unlikely(curctx == irqctx)) return 0; /* build the stack frame on the IRQ stack */ isp = (u32 *) ((char *)irqctx + sizeof(*irqctx)); irqctx->tinfo.task = curctx->tinfo.task; irqctx->tinfo.previous_esp = current_stack_pointer; /* Copy the preempt_count so that the [soft]irq checks work. */ irqctx->tinfo.preempt_count = curctx->tinfo.preempt_count; if (unlikely(overflow)) call_on_stack(print_stack_overflow, isp); asm volatile("xchgl %