为什么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

相关推荐

  • Linux如何快速识别磁盘类型?

    使用 lsblk 命令(推荐)lsblk 是最直观的工具,可显示磁盘的物理类型和拓扑关系:lsblk -d -o NAME,MODEL,SIZE,TRAN,TYPE输出示例:NAME MODEL SIZE TRAN TYPEsda Samsung SSD 870 1TB sata disk # SATA固态硬盘……

    2025年8月8日
    10200
  • linux 如何设置挂载

    Linux 中,使用 mount 命令挂载设备或分区,如 `mount /

    2025年8月18日
    12000
  • Linux error13如何解决?

    Linux error13通常指“Permission denied”(权限被拒绝)错误,是用户在操作Linux系统时最常遇到的权限问题之一,该错误可能出现在文件访问、命令执行、服务启动等多种场景下,核心原因是当前用户对目标资源(文件、目录、设备等)缺乏足够的操作权限,解决error13需要从权限管理、安全上下……

    2025年9月9日
    12800
  • Linux系统如何正确添加静态路由并验证配置?

    在Linux系统中,路由是网络通信的核心机制,它决定了数据包从源地址到目的地址的转发路径,正确配置路由对于多网络环境、服务器网关设置或特定网络访问至关重要,本文将详细介绍Linux系统中添加路由的多种方法,包括临时路由和永久路由的配置,涵盖不同场景下的操作步骤及注意事项,Linux路由基础概念Linux系统的路……

    2025年9月23日
    11500
  • Linux系统中跨文件系统复制文件的实现方法有哪些?

    在Linux系统中,跨文件系统复制文件是常见操作,例如从ext4分区复制到xfs分区、从本地磁盘复制到挂载的U盘或网络文件系统(如NFS、SMB)等,由于不同文件系统的底层实现差异(如inode管理、权限控制、支持特性不同),复制时需选择合适的方法以确保文件属性、权限及数据完整性,以下是常用跨文件系统复制方法及……

    2025年10月8日
    11400

发表回复

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

联系我们

400-880-8834

在线咨询: QQ交谈

邮件:HI@E.KD.CN

关注微信