中断频率限制器

编写一个驱动,限制特定中断产生的最高频率

项目概述

中断频率限制器是一个Linux内核驱动项目,旨在控制特定硬件中断的发生频率。通过此驱动,我们可以确保系统不会因某个中断过于频繁而被淹没,从而提高系统的稳定性和响应性。

中断频率限制器驱动 硬件中断 定时器 用户空间 处理程序 频率控制 系统日志

核心功能

技术实现

数据结构

struct irq_rate_limit {
    int irq_number;             // 要限制的中断号
    unsigned long max_rate;     // 最大允许频率(Hz)
    ktime_t last_time;          // 上次中断时间
    atomic_t over_limit_count;  // 超限计数器
    struct timer_list timer;    // 用于频率控制的定时器
    spinlock_t lock;            // 保护数据结构的自旋锁
};

关键函数

函数名 功能描述 参数说明
irq_handler 中断处理函数 irq: 中断号, dev_id: 设备标识
timer_callback 定时器回调函数 data: 传递给定时器的数据
rate_limit_init 初始化频率限制器 irq: 中断号, max_rate: 最大频率
rate_limit_cleanup 清理资源 irq: 中断号

实现逻辑

  1. 注册中断处理函数,替换原有中断处理
  2. 在中断处理中记录时间戳并计算时间间隔
  3. 如果间隔小于允许的最小间隔,则忽略此次中断
  4. 更新最后一次有效中断的时间
  5. 通过sysfs暴露统计信息和配置参数

设计要点:使用高精度定时器(ktime)确保时间测量的准确性,采用自旋锁保护共享数据,避免竞态条件。

示例代码

#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/ktime.h>
#include <linux/timer.h>
#include <linux/spinlock.h>

#define MAX_RATE_DEFAULT 100  // 默认最大频率100Hz

static struct irq_rate_limit limiter;

// 中断处理函数
static irqreturn_t limited_irq_handler(int irq, void *dev_id)
{
    ktime_t now = ktime_get();
    ktime_t delta = ktime_sub(now, limiter.last_time);
    s64 delta_ns = ktime_to_ns(delta);
    
    unsigned long flags;
    spin_lock_irqsave(&limiter.lock, flags);
    
    // 计算最小允许间隔(纳秒)
    s64 min_interval = NSEC_PER_SEC / limiter.max_rate;
    
    if (delta_ns < min_interval) {
        // 中断过于频繁,忽略此次中断
        atomic_inc(&limiter.over_limit_count);
        spin_unlock_irqrestore(&limiter.lock, flags);
        return IRQ_HANDLED;
    }
    
    // 更新最后一次有效中断时间
    limiter.last_time = now;
    spin_unlock_irqrestore(&limiter.lock, flags);
    
    // 这里可以调用原始的中断处理函数
    // original_irq_handler(irq, dev_id);
    
    printk(KERN_INFO "IRQ %d handled at allowed rate\n", irq);
    return IRQ_HANDLED;
}

// 初始化函数
static int __init rate_limiter_init(void)
{
    int ret;
    
    // 初始化限制器
    limiter.irq_number = 10;  // 示例中断号
    limiter.max_rate = MAX_RATE_DEFAULT;
    limiter.last_time = ktime_get();
    atomic_set(&limiter.over_limit_count, 0);
    spin_lock_init(&limiter.lock);
    
    // 注册中断处理函数
    ret = request_irq(limiter.irq_number, limited_irq_handler,
                     IRQF_SHARED, "rate_limited_irq", &limiter);
    if (ret) {
        printk(KERN_ERR "Failed to request IRQ %d\n", limiter.irq_number);
        return ret;
    }
    
    printk(KERN_INFO "IRQ rate limiter loaded for IRQ %d, max rate: %lu Hz\n",
           limiter.irq_number, limiter.max_rate);
    return 0;
}

// 清理函数
static void __exit rate_limiter_exit(void)
{
    free_irq(limiter.irq_number, &limiter);
    printk(KERN_INFO "IRQ rate limiter unloaded\n");
}

module_init(rate_limiter_init);
module_exit(rate_limiter_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux Driver Expert");
MODULE_DESCRIPTION("IRQ Rate Limiter Driver");

注意:在实际项目中,需要添加sysfs接口来动态配置最大频率和查看统计信息,并确保正确处理并发访问。

应用场景

测试方法

可以使用QEMU虚拟环境进行测试:

  1. 编译并加载驱动模块
  2. 使用测试程序生成指定频率的中断
  3. 通过dmesg查看驱动日志输出
  4. 验证频率限制功能是否正常工作