由于中断处理程序是异步的,因此在中断处理程序中执行的操作应该尽可能少。因此,一种更好的方法是创建一个线程,以便在主线程中处理中断事件。下面是一个简单的例子,说明如何在Linux下实现中断线程化的驱动程序。

首先,我们需要定义中断处理程序。在本例中,我们将使用GPIO中断。当GPIO引脚的值发生变化时,将触发中断。

#include <linux/interrupt.h>
#include <linux/gpio.h>

#define GPIO_PIN 17

static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
{
    printk(KERN_INFO 'GPIO IRQ\n');
    return IRQ_HANDLED;
}

static int gpio_init(void)
{
    int ret;
    
    if ((ret = gpio_request(GPIO_PIN, 'interrupt')) < 0) {
        printk(KERN_ERR 'gpio_request failed\n');
        return ret;
    }
    
    if ((ret = gpio_direction_input(GPIO_PIN)) < 0) {
        printk(KERN_ERR 'gpio_direction_input failed\n');
        gpio_free(GPIO_PIN);
        return ret;
    }
    
    if ((ret = request_irq(gpio_to_irq(GPIO_PIN), gpio_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 'gpio_interrupt', NULL)) < 0) {
        printk(KERN_ERR 'request_irq failed\n');
        gpio_free(GPIO_PIN);
        return ret;
    }
    
    return 0;
}

static void gpio_exit(void)
{
    free_irq(gpio_to_irq(GPIO_PIN), NULL);
    gpio_free(GPIO_PIN);
}

module_init(gpio_init);
module_exit(gpio_exit);

在中断处理程序中,我们只是输出一条消息。现在我们需要创建一个线程,以便在主线程中处理中断事件。为此,我们需要创建一个新的内核线程,该线程将采取以下步骤:

  1. 等待中断事件。
  2. 处理中断事件。
  3. 重复步骤1和2。
#include <linux/kthread.h>

static struct task_struct *thread;
static wait_queue_head_t wait_queue;

static int thread_func(void *data)
{
    while (!kthread_should_stop()) {
        wait_event_interruptible(wait_queue, kthread_should_stop());
        printk(KERN_INFO 'Thread running\n');
        // do some work
    }
    
    return 0;
}

static int gpio_init(void)
{
    int ret;
    
    init_waitqueue_head(&wait_queue);
    
    if ((ret = gpio_request(GPIO_PIN, 'interrupt')) < 0) {
        printk(KERN_ERR 'gpio_request failed\n');
        return ret;
    }
    
    if ((ret = gpio_direction_input(GPIO_PIN)) < 0) {
        printk(KERN_ERR 'gpio_direction_input failed\n');
        gpio_free(GPIO_PIN);
        return ret;
    }
    
    if ((ret = request_irq(gpio_to_irq(GPIO_PIN), gpio_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 'gpio_interrupt', NULL)) < 0) {
        printk(KERN_ERR 'request_irq failed\n');
        gpio_free(GPIO_PIN);
        return ret;
    }
    
    thread = kthread_create(thread_func, NULL, 'interrupt_thread');
    if (IS_ERR(thread)) {
        ret = PTR_ERR(thread);
        printk(KERN_ERR 'kthread_create failed\n');
        free_irq(gpio_to_irq(GPIO_PIN), NULL);
        gpio_free(GPIO_PIN);
        return ret;
    }
    
    wake_up_process(thread);
    
    return 0;
}

static void gpio_exit(void)
{
    kthread_stop(thread);
    free_irq(gpio_to_irq(GPIO_PIN), NULL);
    gpio_free(GPIO_PIN);
}

module_init(gpio_init);
module_exit(gpio_exit);

在这个例子中,我们使用了wait_queue_head_twait_event_interruptible来等待中断事件。wait_event_interruptible将线程置于睡眠状态,直到中断事件发生或线程应该停止。中断处理程序将唤醒睡眠的线程,并执行一些操作。

在本例中,我们只是输出一条消息,但是您可以执行任何需要执行的操作。

Linux 中断线程化驱动程序示例

原文地址: https://www.cveoy.top/t/topic/lHeo 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录