目录
1. 前言
本专题我们开始学习进程管理部分。本文主要参考了《奔跑吧, Linux内核》、ULA、ULK的相关内容。
本节记录ARM架构下中断是如何管理的,Linux内核中的中断管理机制是如何设计与实现的,以及常用的下半部机制,如软中断、tasklet、workqueue等。本文及后续中断相关笔记均以qemu 5.0.0内嵌平台为例,中断控制器采用GIC-400控制器,支持GIC version2技术规范。本文主要以GIC为例记录注册中断的过程。
kernel版本:5.10
平台:arm64
注:
为方便阅读,正文标题采用分级结构标识,每一级用一个"-“表示,如:两级为”|- -", 三级为”|- - -“
2. 注册中断接口
接口说明
- request_irq
/**
* request_irq - Add a handler for an interrupt line
* @irq: The interrupt line to allocate
* @handler: Function to be called when the IRQ occurs.
* Primary handler for threaded interrupts
* If NULL, the default primary handler is installed
* @flags: Handling flags
* @name: Name of the device generating this interrupt
* @dev: A cookie passed to the handler function
*
* This call allocates an interrupt and establishes a handler; see
* the documentation for request_threaded_irq() for details.
*/
static inline int __must_check
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)
{
return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}
中断注册旧有接口,实际是对request_threaded_irq接口的封装,其中线程处理函数为NULL
- request_threaded_irq
/**
* request_threaded_irq - allocate an interrupt line
* @irq: Interrupt line to allocate
* @handler: Function to be called when the IRQ occurs.
* Primary handler for threaded interrupts
* If NULL and thread_fn != NULL the default
* primary handler is installed
* @thread_fn: Function called from the irq handler thread
* If NULL, no irq thread is created
* @irqflags: Interrupt type flags
* @devname: An ascii name for the claiming device
* @dev_id: A cookie passed back to the handler function
*
* This call allocates interrupt resources and enables the
* interrupt line and IRQ handling. From the point this
* call is made your handler function may be invoked. Since
* your handler function must clear any interrupt the board
* raises, you must take care both to initialise your hardware
* and to set up the interrupt handler in the right order.
*
* If you want to set up a threaded irq handler for your device
* then you need to supply @handler and @thread_fn. @handler is
* still called in hard interrupt context and has to check
* whether the interrupt originates from the device. If yes it
* needs to disable the interrupt on the device and return
* IRQ_WAKE_THREAD which will wake up the handler thread and run
* @thread_fn. This split handler design is necessary to support
* shared interrupts.
*
* Dev_id must be globally unique. Normally the address of the
* device data structure is used as the cookie. Since the handler
* receives this value it makes sense to use it.
*
* If your interrupt is shared you must pass a non NULL dev_id
* as this is required when freeing the interrupt.
*
* Flags:
*
* IRQF_SHARED Interrupt is shared
* IRQF_TRIGGER_* Specify active edge(s) or level
*
*/
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
irq_handler_t thread_fn, unsigned long irqflags,
const char *devname, void *dev_id)
在Linux2.6.30引入,是线程化的中断注册函数。由于可以把中断处理中的一些繁重任务作为内核线程执行,可以大大减少由于中断导致实时进程的延迟。
| 参数 | 说明 |
|---|---|
| irq | IRQ软中断号 |
| handler | primary handler,中断发生时优先执行primary handler,如果primary handler为NULL且 thread_fn不为空,那么系统执行默认的primary handler:irq_default_primary_handler() |
| thread_fn | 中断线程化的处理程序,如果不为空会创建一个内核线程。handler和thread_fn不能同时为空 |
| irqflags | 中断标志位 |
| devname | 该中断名称 |
| dev id | 传递给中断处理程序的参数 |
IRQF_*中断标志位
<include/linux/interrupt.h>
/*
* These flags used only by the kernel as part of the
* irq handling routines.
*
* IRQF_SHARED - allow sharing the irq among several devices
* IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur
* IRQF_TIMER - Flag to mark this interrupt as timer interrupt
* IRQF_PERCPU - Interrupt is per cpu
* IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing
* IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is
* registered first in a shared interrupt is considered for
* performance reasons)
* IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished.
* Used by threaded interrupts which need to keep the
* irq line disabled until the threaded handler has been run.
* IRQF_NO_SUSPEND - Do not disable this IRQ during suspend. Does not guarantee
* that this interrupt will wake the system from a suspended
* state. See Documentation/power/suspend-and-interrupts.rst
* IRQF_FORCE_RESUME - Force enable it on resume even if IRQF_NO_SUSPEND is set
* IRQF_NO_THREAD - Interrupt cannot be threaded
* IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device
* resume time.
* IRQF_COND_SUSPEND - If the IRQ is shared with a NO_SUSPEND user, execute this
* interrupt handler after suspending interrupts. For system
* wakeup devices users need to implement wakeup detection in
* their interrupt handlers.
*/
/*多个设备共享一个中断号,需要硬件支持以区分哪个设备发生的中断*/
#define IRQF_SHARED 0x00000080
#define IRQF_PROBE_SHARED 0x00000100
#define __IRQF_TIMER 0x00000200
/*属于特定某个cpu的中断*/
#define IRQF_PERCPU 0x00000400
/*禁止多CPU的中断均衡*/
#define IRQF_NOBALANCING 0x00000800
/*中断被用作轮询*/
#define IRQF_IRQPOLL 0x00001000
/*
*表示一次性触发的中断,不能嵌套。
*(1)在硬件中断处理完成之后才能打开中断;
*(2)在中断线程化中保持中断关闭状态,直到该中断源上所有的thread_fn完成之后才能打开中断:
*(3)如果request threaded irq()时primary handler为NULL且中断控制器不支持硬件ONESHOT功能,那应该显示地设置该标志位?
*/
#define IRQF_ONESHOT 0x00002000
/*系统睡眠过程中不要关闭该中断*/

本文详细解读了ARM平台Linux内核中中断管理的request_threaded_irq接口,包括中断标志位(IRQF_*、IRQS_*、IRQD_*)的作用,以及如何注册中断、线程化处理和中断状态管理。着重介绍了共享中断和非共享中断的处理策略。
最低0.47元/天 解锁文章
527

被折叠的 条评论
为什么被折叠?



