Blog icon indicating copy to clipboard operation
Blog copied to clipboard

Chapter 7 Interrupts and Interrupt Handlers

Open jason--liu opened this issue 4 years ago • 0 comments

中断处理程序与其他内核函数的区别在于内核调用它们来响应中断,并且它们运行在称为中断上下文的特殊上下文中;中断上下午也称为原子上下文,中断上下文不可调度。 处理程序必须快速运行,以便尽快恢复执行中断的代码,提高系统响应。

上半部和下半部

上半部通常是执行时间非常短,需要尽快完成。下半部是处理可以延迟的工作

中断处理函数

注册中断

/* request_irq: allocate a given interrupt line */
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev)

typedef irqreturn_t (*irq_handler_t)(int, void *);

中断处理FLag

  • IRQF_DISABLED When set, this flag instructs the kernel to disable all interrupts when executing this interrupt handler.When unset, interrupt handlers run with all interrupts except their own enabled. 大多数中断处理都不需要设置这个flag,主要用在性能敏感并且执行非常快的中断中。
  • IRQF_SAMPLE_RANDOM 这个标志指定这个设备产生的中断应该贡献给内核熵池。内核熵池提供源自各种随机事件的真正随机数。
  • IRQF_TIMER This flag specifies that this handler processes interrupts for the system timer.
  • IRQF_SHARED This flag specifies that the interrupt line can be shared among multiple interrupt handlers

可以通过/proc/irq/proc/interrupts查看中断信息。request_irq()可以睡眠。 释放中断

void free_irq(unsigned int irq, void *dev)

中断控制

关闭中断也就关闭了抢占。 锁能防止其他处理器并发访问,中断能防止中断处理程序并发访问临界区;锁一般和关中断同时使用。

使能和失能中断

针对当前处理器开关中断

local_irq_disable();
/* interrupts are disabled .. */
local_irq_enable();

local_irq_disable()函数是不安全的;因为随着内核的大小和复杂性的增加,导致函数的所有代码路径变得越来越困难,所以在禁用中断系统之前保存它的状态要安全得多。

unsigned long flags;
local_irq_save(flags); /* interrupts are now disabled */
/* ... */
local_irq_restore(flags); /* interrupts are restored to their previous state */

?? 上面两个函数调用必须在同一个函数中。前面所有的函数在中断上下文和进程上下文中都可以调用。

失能指定中断

void disable_irq(unsigned int irq);
void disable_irq_nosync(unsigned int irq);
void enable_irq(unsigned int irq);
void synchronize_irq(unsigned int irq);

前两个函数禁用中断控制器中的给定中断线,所有处理器都不会收到这个中断disable_irq会等待当前正在执行的中断处理函数执行完成。因此,调用者不仅可以保证新的中断不会在给定的线路上传递,而且任何已经执行的处理程序都已经退出。disable_irq_nosync()不会等待中断执行完成。函数synchronize_irq等待特定的中断处理程序退出(如果它正在执行),然后返回。 disable_irq或者disable_irq_nosync必须和enable_irq配对使用,即调用次数一样。对于共享中断,disable_irq是不应该使用的。

中断系统状态

知道当前中断是打开还是关闭,或者是否在中断上下文中是非常有用的。 函数 irqs_disabled()如果当前处理器中断关闭返回非0,否则返回0. 有两个宏可以检查是否在中断上下文中。

in_interrupt()
in_irq()

in_interrupt通常用的比较多,如果内核在中断上下文(包括中断上下半部)返回非0,否则返回0(即进程上下文)。in_irq只是用来判断是否在中断上半部,如果是,返回非0.

image

jason--liu avatar Jul 05 '21 15:07 jason--liu