为什么90后频繁跳槽成常态?

在Linux内核中申请中断是设备驱动程序开发的核心任务之一,它允许硬件设备在需要处理时主动通知CPU,以下是详细的技术流程和注意事项:


中断申请的核心函数

Linux内核通过 request_irq()request_threaded_irq() 函数申请中断:

int request_irq(unsigned int irq, irq_handler_t handler, 
                unsigned long flags, const char *name, void *dev);
  • 参数解析
    • irq:中断号(如硬件IRQ编号),可通过 platform_get_irq()pci_irq_vector() 获取。
    • handler:中断处理函数指针,类型为 irqreturn_t (*handler)(int, void*)
    • flags:控制中断行为的标志位,常用值:
      • IRQF_SHARED:允许多个设备共享同一中断线。
      • IRQF_TRIGGER_RISING:上升沿触发。
      • IRQF_ONESHOT:线程化中断中确保中断线保持禁用直到处理完成。
    • name:在 /proc/interrupts 中显示的设备标识。
    • dev:传递给处理函数的私有数据指针(必须唯一,用于共享中断)。

中断处理函数编写规范

处理函数需遵循固定原型:

irqreturn_t my_handler(int irq, void *dev_id) {
    // 1. 快速处理:读取状态寄存器、清除中断标志
    // 2. 若需耗时操作,触发下半部(如tasklet/workqueue)
    return IRQ_HANDLED; // 或 IRQ_NONE(非本设备中断)
}

关键要求

  • 非阻塞:禁止使用睡眠函数(如 mutex_lock()kmalloc(GFP_KERNEL))。
  • 短时执行:理想执行时间 < 100微秒,避免影响系统响应。

线程化中断(推荐方式)

通过 request_threaded_irq() 将中断分为顶半部(快速响应)和底半部(线程中执行):

int request_threaded_irq(unsigned int irq, 
                         irq_handler_t handler,   // 顶半部
                         irq_handler_t thread_fn, // 底半部(线程内运行)
                         unsigned long flags, 
                         const char *name, 
                         void *dev);
  • 优势
    • 底半部可睡眠、执行复杂逻辑。
    • 避免中断屏蔽时间过长。
  • 示例
    request_threaded_irq(irq, NULL, my_thread_fn, 
                        IRQF_ONESHOT, "my_device", dev);

完整代码示例

以PCI设备驱动为例:

static irqreturn_t my_interrupt(int irq, void *dev_id) {
    struct my_device *dev = dev_id;
    if (!check_hw_irq(dev)) 
        return IRQ_NONE; // 非本设备中断
    return IRQ_WAKE_THREAD; // 唤醒底半部线程
}
static irqreturn_t my_thread_fn(int irq, void *dev_id) {
    struct my_device *dev = dev_id;
    process_data(dev); // 执行耗时操作
    return IRQ_HANDLED;
}
static int probe(struct pci_dev *pdev, const struct pci_device_id *id) {
    int irq = pci_irq_vector(pdev, 0);
    ret = request_threaded_irq(irq, my_interrupt, my_thread_fn,
                              IRQF_SHARED | IRQF_ONESHOT,
                              "my_pci_card", pdev);
    if (ret) 
        dev_err(&pdev->dev, "Failed to request IRQ %d\n", irq);
    return ret;
}
static void remove(struct pci_dev *pdev) {
    free_irq(pci_irq_vector(pdev, 0), pdev);
}

关键注意事项

  1. 中断号获取
    • 旧方法:直接使用硬件IRQ(如 5),已废弃
    • 现代方法:通过设备树(DT)或ACPI动态获取(如 platform_get_irq())。
  2. 共享中断
    • 必须设置 IRQF_SHARED
    • dev_id 必须是设备唯一标识(通常用设备结构体指针)。
  3. 资源释放
    • 在驱动卸载或错误路径调用 free_irq(irq, dev_id)
    • 否则导致内核崩溃或中断泄漏。
  4. 中断统计
    • 查看 /proc/interrupts 确认中断是否成功注册及触发次数。

最佳实践

  • 优先选择线程化中断:避免实时性任务被长时间中断阻塞。
  • 避免共享中断:除非硬件设计强制要求(如PCI设备)。
  • 中断亲和性:通过 irq_set_affinity() 绑定中断到特定CPU核心,优化多核性能。
  • 锁的使用:在中断上下文中,优先使用自旋锁(spin_lock_irqsave())。

常见错误

  • 未返回 IRQ_WAKE_THREAD:线程化中断中顶半部必须返回此值以唤醒底半部。
  • 遗漏 free_irq:引发 “Trying to free already-free IRQ” 内核错误。
  • 阻塞操作:在非线程化处理函数中调用可能睡眠的API。

正确申请中断是驱动稳定性的基石,开发者需深入理解硬件特性(如触发方式)和内核约束(如执行上下文),对于新开发,线程化中断是首选方案,它平衡了实时性与安全性,实际开发中务必参考最新内核文档(如 Linux Kernel Interrupt Handling),并利用 ftraceperf 工具监控中断延迟。

引用说明: 基于 Linux 内核 6.x 版本文档、《Linux Device Drivers, 3rd Edition》(O’Reilly)及内核源码(include/linux/interrupt.h),实践代码遵循 GPL-2.0 许可,技术细节以 kernel.org 官方文档为准。

原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/6584.html

(0)
酷番叔酷番叔
上一篇 2025年7月7日 14:02
下一篇 2025年7月7日 14:11

相关推荐

  • Ubuntu能否替代Windows系统?

    在Linux服务器上搭建PHP环境是部署动态网站的关键步骤,以下为详细操作指南,遵循最佳实践并兼顾安全性与性能:环境准备系统选择推荐Ubuntu 22.04 LTS或CentOS 7+(需已配置sudo权限用户)更新系统: sudo apt update && sudo apt upgrade……

    2025年6月17日
    11500
  • 如何修改Linux系统的待机休眠时间与唤醒设置?

    在Linux系统中,待机时间的设置涉及屏幕关闭、硬盘休眠、系统挂起等多个方面,合理调整既能节省能源,又能避免频繁唤醒硬件带来的损耗,以下是修改Linux待机时间的详细方法,涵盖图形界面、命令行工具及系统级配置,适用于不同使用场景和用户需求,通过桌面环境图形界面修改(适合普通用户)主流Linux桌面环境(如GNO……

    2025年10月3日
    9500
  • linux中如何查看设备信息

    Linux中,可使用lsblk查看块设备信息,lspci

    2025年8月18日
    9000
  • Linux批量改名怎样又快又稳?

    使用 rename 命令(推荐)rename 是专为批量重命名设计的工具,支持正则表达式,语法简洁高效,基本语法:rename 's/旧内容/新内容/' 匹配模式场景示例:替换固定字符串(如将 file_old.txt 改为 file_new.txt):rename 's/old/new……

    2025年7月17日
    10600
  • linux如何制作镜像

    Linux 中,可使用 dd 命令制作镜像,如 `dd if=/dev/sdX of=/path/to/image.

    2025年8月10日
    10700

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-880-8834

在线咨询: QQ交谈

邮件:HI@E.KD.CN

关注微信