Linux外部事件处理-IRQ与轮询kthread



我正在将一个设备驱动程序从QNX移植到Linux。在QNX中,旧的驱动程序使用带有无限循环的pthread来监视中断的发生,而不是注册一个真正的中断处理程序。为了证明使用register_irq()而不是专用轮询线程的有效性,我在Linux中编写了两个驱动程序。每个的相关代码如下所示,问题在底部。

IRQ

写入处理程序

irqreturn_t timing_interrupt_handler(int irq, void *dev_id) {
  u32 test;
  /* read device interrupt command/status register */
  test = ioread32(timing_card[3].base);
  /* sanity check that the device reported the interrupt */
  if ( test & (1 << 2) ) {
    /* clear interrupt status */
    iowrite32( 0x0d, timing_card[3].base);
    /* toggle digital output line */
    test = ioread32(timing_card[2].base);
    if ( test & 0x01 ) 
      iowrite32(test & ~0x1, timing_card[2].base);
    else
      iowrite32(test |  0x1, timing_card[2].base);
  }
  return IRQ_HANDLED;
}

注册处理程序

rc = request_irq(irq_line, timing_interrupt_handler,
               IRQF_SHARED, "timing", timing_card);
if ( rc ) {
  printk(KERN_ALERT "Failed to register irq %dn", irq_line);
  return rc;
}

轮询线程

编写线程函数

int poll_irq(void *data) {
  u32 test;
  /* until module unload */
  while ( !kthread_should_stop() ) {
    /* read device interrupt command/status register */
    test = ioread32(timing_card[3].base);
    /* sanity check that the device reported the interrupt */
    if ( test & (1 << 2) ) {
      /* clear interrupt status */
      iowrite32( 0x0d, timing_card[3].base);
      /* toggle digital output line */
      test = ioread32(timing_card[2].base);
      if ( test & 0x01 ) 
        iowrite32(test & ~0x1, timing_card[2].base);
      else
        iowrite32(test |  0x1, timing_card[2].base);      
      }
      else
        usleep_range(9, 11);
  }
  return 0;
}

开始线程

kthread = kthread_create(poll_irq, 0x0, "poll_IRQ_test");
wake_up_process(kthread);

问题

当我在示波器上放两条轨迹时——一条监测卡的数字输入(会触发中断),另一条监测卡的数字输出(会对中断做出反应),我可以测量对事件的反应时间。

第一种"正确"的方法,注册一个IRQ,大约需要80微秒。

第二种方法,运行一个无限线程,大约需要15-30微秒。

什么东西?第一种方法的好处是它不会浪费那么多处理能力,但为什么响应时间会受到如此大的影响?有这个轮询线程真的有多糟糕?如何调查并最终证明轮询线程给CPU带来的额外开销?

谢谢你抽出时间!

最佳

Scott

中断响应时间受系统(无论是什么)需要提供中断的时间以及CPU(无论是哪个)需要从某种节能睡眠模式中唤醒的时间的影响。

轮询线程消耗CPU时间和电源。要测量它们,请使用类似toppowertop的东西,或者直接在硬件上测量功耗。

最新更新