Linux irq_poll忙轮询中断模式与cap_poll适配
irq_poll是Linux内核提供的一种中断与轮询混合机制,用于在高中断频率场景下降低中断开销。它由include/linux/irq_poll.h和lib/irq_poll.c实现。当设备中断频率超过一定阈值时,irq_poll自动将中断模式切换为轮询模式,避免频繁的硬件中断上下文切换消耗CPU时间。
irq_poll的核心数据结构:
```c
struct irq_poll {
struct list_head list;
unsigned long state;
int (*poll)(struct irq_poll *, int budget);
unsigned int irq;
};
```
state字段使用位操作管理状态,关键标志位如下:
```c
#define IRQ_POLL_F_SCHED 0
#define IRQ_POLL_F_POLLING 1
#define IRQ_POLL_F_DISABLE 2
```
初始化一个irq_poll实例使用irq_poll_init:
```c
void irq_poll_init(struct irq_poll *iop, int irq,
int (*poll)(struct irq_poll *, int))
{
INIT_LIST_HEAD(&iop->list);
iop->state = 0;
iop->irq = irq;
iop->poll = poll;
}
```
irq_poll的核心调度入口是irq_poll_sched,通常在中断处理handler中调用:
```c
void irq_poll_sched(struct irq_poll *iop)
{
if (test_and_set_bit(IRQ_POLL_F_SCHED, &iop->state))
return;
list_add_tail(&iop->list, this_cpu_ptr(&blk_cpu_iopoll));
__raise_softirq_irqoff(IRQ_POLL_SOFTIRQ);
}
```
该函数将irq_poll实例加入per-CPU链表blk_cpu_iopoll,然后触发IRQ_POLL_SOFTIRQ软中断。软中断处理函数irq_poll_softirq在软中断上下文中执行轮询回调:
```c
static void irq_poll_softirq(struct softirq_action *h)
{
int pending = 0, budget = irq_poll_budget;
LIST_HEAD(list);
local_irq_disable();
list_splice_init(this_cpu_ptr(&blk_cpu_iopoll), &list);
local_irq_enable();
while (!list_empty(&list)) {
struct irq_poll *iop;
int work_done;
iop = list_entry(list.next, struct irq_poll, list);
work_done = iop->poll(iop, budget);
budget -= min(budget, work_done);
if (work_done && budget) {
list_move_tail(&iop->list, &list);
pending++;
} else {
list_del_init(&iop->list);
clear_bit(IRQ_POLL_F_SCHED, &iop->state);
if (work_done && budget)
pending++;
}
}
if (pending) {
list_splice_tail_init(&list, this_cpu_ptr(&blk_cpu_iopoll));
__raise_softirq_irqoff(IRQ_POLL_SOFTIRQ);
}
local_irq_disable();
list_splice_tail_init(&list, this_cpu_ptr(&blk_cpu_iopoll));
local_irq_enable();
}
```
轮询回调用budget参数控制本次轮询的处理上限,防止独占CPU。irq_poll_budget默认值为64,表示每次软中断最多处理64个数据包或请求。如果poll返回的工作量等于budget,说明仍有数据待处理,irq_poll_softirq将重新触发软中断继续轮询。如果工作量小于budget,说明设备已空,清除IRQ_POLL_F_SCHED标志返回中断模式。
cap_poll是在网络驱动NAPI poll基础上的IRQ层面扩展。部分设备通过set_irq_poll_cap接口标记自身支持poll能力:
```c
void irq_poll_set_cap(struct irq_poll *iop)
{
set_bit(IRQ_POLL_F_DISABLE, &iop->state);
}
```
将IRQ_POLL_F_DISABLE置位后,irq_poll会在特定条件下禁用自身并退还中断模式。这个自适应切换是irq_poll区别于NAPI的关键点。irq_poll通过统计中断间隔时间动态判断是否切换:
```c
static bool irq_poll_check_poll(struct irq_poll *iop, unsigned int irq_interval)
{
if (irq_interval < irq_poll_timeout)
return true;
return false;
}
```
当连续中断间隔小于irq_poll_timeout(默认200微秒)时,中断频率过高,irq_poll倾向于保持在轮询模式;当间隔变大时,切换回中断模式以节省CPU。
与NAPI相比,irq_poll的差异在于:
1. irq_poll工作在软中断IRQ_POLL_SOFTIRQ中,NAPI使用NET_RX_SOFTIRQ,两者优先级不同。
2. irq_poll的poll回调在软中断上下文每次被调用时最多执行budget次,NAPI的poll在每次被调用时有固定的budget配额。
3. irq_poll不需要像NAPI那样禁用设备的RX中断,它仅通过IRQ_POLL_F_SCHED标志控制调度,中断handler依然简短地记录状态。
irq_poll与线程化中断的使用场景对比:中断频率较低时,线程化中断将处理推入进程上下文节省CPU;中断频率极高(如万兆网卡)时,线程化导致频繁唤醒和调度,此时irq_poll在软中断中轮询更高效。
```c
static int example_irq_handler(int irq, void *dev_id)
{
struct my_device *dev = dev_id;
/* Quick hardware check */
if (!readl(dev->regs + INT_STATUS))
return IRQ_NONE;
/* Schedule irq_poll instead of processing all data */
irq_poll_sched(&dev->iop);
return IRQ_HANDLED;
}
static int my_device_poll(struct irq_poll *iop, int budget)
{
struct my_device *dev = container_of(iop, struct my_device, iop);
int work = 0;
while (work < budget) {
u32 status = readl(dev->regs + RX_STATUS);
if (!(status & RX_READY))
break;
/* Process one packet */
work++;
}
if (work < budget) {
/* No more data, re-enable interrupts */
writel(INT_ENABLE, dev->regs + INT_MASK);
}
return work;
}
```
在这个示例中,IRQ handler仅检查状态并调用irq_poll_sched,实际数据收发在poll回调中轮询完成。这种设计将高频率中断转换为有节制的轮询,兼顾了延迟和吞吐量。
Linux irq_poll忙轮询中断模式与cap_poll适配
张小明
前端开发工程师
两天实训,跑通P600无人机开发
5月28日-29日,阿木实验室 P600无人机培训课在成都顺利开展。本次培训围绕 P600无人机平台展开,课程内容覆盖无人机基础知识、MAVROS 控制接口、Prometheus 软件框架、理论仿真以及多项实飞演示,帮助学员从系统原理到实际操作,更完…
M68040总线监听机制:多主系统缓存一致性硬件实现详解
1. 多主系统缓存一致性的核心挑战与M68040的应对之道在嵌入式系统和早期的多处理器架构设计中,一个核心且棘手的问题就是缓存一致性。想象一下,在一个系统中,有多个“大脑”(处理器或DMA控制器等总线主设备)都能独立地…
多维聚合实战:从SQL GROUP BY到OLAP立方体的数据变形术
1. 这不是简单的“加总求平均”——多维聚合中的数据变形术到底在解决什么问题?如果你正在处理销售报表、用户行为宽表、IoT设备时序快照,或者哪怕只是Excel里一张带地区、月份、产品线、渠道四个维度的汇总表,那你大概率已经踩进过这个坑&am…
NXP DSP56720/56721 GPIO与ESAI接口配置实战指南
1. 项目概述与核心价值如果你正在开发基于Freescale(现NXP)Symphony DSP56720或DSP56721的音频处理系统,那么对GPIO和ESAI接口的深入理解和精准配置,绝对是项目成败的关键一步。这两颗芯片作为经典的多核音频DSP,在专业…
AlienFX Tools终极指南:免费快速解决Alienware灯光控制失效问题
AlienFX Tools终极指南:免费快速解决Alienware灯光控制失效问题 【免费下载链接】alienfx-tools Alienware systems lights, fans, and power control tools and apps 项目地址: https://gitcode.com/gh_mirrors/al/alienfx-tools AlienFX Tools是一款专为Al…
终极指南:5分钟为WPS Office安装Zotero插件,科研写作效率提升10倍
终极指南:5分钟为WPS Office安装Zotero插件,科研写作效率提升10倍 【免费下载链接】WPS-Zotero An add-on for WPS Writer to integrate with Zotero. 项目地址: https://gitcode.com/gh_mirrors/wp/WPS-Zotero 还在为学术论文中的文献引用而烦恼…