linux中断下文工作队列之延迟工作(中断六)

一、延迟工作介绍

  延迟工作是一种将工作的执行延迟到稍后时间点进行处理的技术。通常情况下,当某个任务需要花费较长时间,不需要立即执行或需要按时执行时,延迟工作就会派上用场。
  延迟工作的基本思想是将任务放入一个队列中,然后由后台的工作进程会任务调度程序来处理队列中的任务。任务可以在指定的延迟时间后执行,也可以根据优先级,任务类型或者其他条件进行排序和处理。
  延迟工作在许多应用场景中都非常有用,尤其是在需要处理大量任务,提供系统性能和可靠性的情况下。以下是一些常用的应用场景
  1 延迟工作常用于处理那些需要花费较长时间的任务,比如发送电子邮件,处理图像等。通过将这些任务放入队列中并延迟执行,可以避免阻塞应用程序的主线程,提高系统的响应速度。
  2 延迟工作可以用来执行定时任务,比如定时备份数据库,通过将任务设置为在未来的某个时间点执行,提高系统的可靠性和效率。
  例如按键消抖除了使用定时器方式进行消抖,也可以使用延迟工作来消抖。
  在 Linux 内核中,使用 struct delayed_work 来描述延迟工作,定义在include/linux/workqueue.h 当中,原型定义如下所示:

struct delayed_work{
    
    
struct work_struct work;// 延迟工作的基本工作结构
struct timer_list timer;// 定时器,用于延迟执行工作
};

  struct delayed_work 结构体包含了两个成员:
  1 work:这是一个 struct work_struct 类型的成员,用于表示延迟工作的基本工作结构。structwork_struct 是表示工作的常见数据结构,用于定义要执行的工作内容。
  2 timer:这是一个 struct timer_list 类型的成员,用于管理延迟工作的定时器。struct timer_list是 Linux 内核中的定时器结构,用于设置延迟时间和触发工作执行的时机。
  使用 struct delayed_work 结构体,可以将需要执行的工作封装成一个延迟工作,并使用定时器来控制工作的延迟执行。通过设置定时器的延迟时间,可以指定工作在一定时间后执行。

二、延迟工作相关接口函数

2.1、初始化延迟工作函数

  静态定义并初始化延迟工作使用宏 DECLARE_DELAYED_WORK,函数原型如下所示:

#define DECLARE_DELAYED_WORK(n,f) struct delayed_work n = {
      
       .work = __WORK_INITIALIZER(n.work, (f)) }

  使用宏定义后,可以将上述代码简化为#define DECLARE_DELAYED_WORK(n,f),n代表延迟工作的变量名,f 是延迟工作的处理函数。
  动态定义并初始化延迟工作使用宏 INIT_DELAYED_WORK,函数原型如下所示:

#define INIT_DELAYED_WORK(_work, _func) \
do {
      
       \
INIT_WORK(&(_work)->work, (_func)); \
(_work)->timer = TIMER_INITIALIZER((_work)->timer, 0, 0); \
} while (0)

  使用宏定义后,可以将上述代码简化为#define INIT_DELAYED_WORK(_work, _func),n代表延迟工作的变量名,f 是延迟工作的处理函数。

2.2、调度延迟工作函数

  如果是在共享工作队列上调度延迟工作,使用以下函数:

static inline bool schedule_delayed_work(struct delayed_work *dwork,unsigned long delay )

  该函数是一个内联函数,用于在给定的延迟时间后调度延迟工作执行。函数参数 dwork:是指向延迟工作的指针,即要被调度的延迟工作。delay:表示延迟的时间长度,以内核时钟节拍数 jiffies 为单位。
  如果是在自定义工作队列上调度延迟工作,使用以下函数:

static inline bool queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork, unsigned long delay)

  该函数是一个内联函数,用于将延迟工作加入工作队列后在指定的延迟时间后执行。函数参数 wq 是指向工作队列结构的指针,即要将延迟工作加入的目标工作队列。dwork:指向延迟工作的指针,也就是要被加入工作队列的延迟工作。delay: 表示延迟的时间长度,以内核时钟节拍数 jiffies 为单位。

2.3、取消调度延迟工作函数

  如果要取消调度函数,使用以下函数:

extern bool cancel_delayed_work_sync(struct delayed_work *dwork);

  该函数是一个外部声明的函数,用于取消延迟工作并等待其完成。dwork 参数是指向延迟工作的指针,也就是要被取消的延迟工作。函数如果返回 true,说明成功取消延迟工作并等待其完成。函数如果返回 false,说明无法取消延迟工作或等待其完成。

三、代码示例

3.1、驱动层程序

#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/workqueue.h>

int irq;
struct workqueue_struct *test_workqueue;
struct delayed_work test_workqueue_work;

// 工作项处理函数
void test_work(struct work_struct *work)
{
    
    
  msleep(1000);
  printk("This is test_work\n");
}

// 中断处理函数
irqreturn_t test_interrupt(int irq, void *args)
{
    
    
  printk("This is test_interrupt\n");
  // 提交延迟工作项到自定义工作队列
  queue_delayed_work(test_workqueue, &test_workqueue_work, 3 * HZ); 
  return IRQ_RETVAL(IRQ_HANDLED);
}

static int interrupt_irq_init(void)
{
    
    
  int ret;
  irq = gpio_to_irq(101); // 将GPIO映射为中断号
  printk("irq is %d\n", irq);

  // 请求中断
  ret = request_irq(irq, test_interrupt, IRQF_TRIGGER_RISING, "test", NULL);
  if (ret < 0)
  {
    
    
    printk("request_irq is error\n");
    return -1;
  }
  // 创建工作队列
  test_workqueue = create_workqueue("test_workqueue"); 
  // 初始化延迟工作项
  INIT_DELAYED_WORK(&test_workqueue_work, test_work);  

  return 0;
}

static void interrupt_irq_exit(void)
{
    
    
  free_irq(irq, NULL);                            // 释放中断
  cancel_delayed_work_sync(&test_workqueue_work); // 取消延迟工作项
  flush_workqueue(test_workqueue);                // 刷新工作队列
  destroy_workqueue(test_workqueue);              // 销毁工作队列
  printk("bye bye\n");
}

module_init(interrupt_irq_init);
module_exit(interrupt_irq_exit);

3.2、linux中断下文工作队列之延迟工作使用API要点

  // 初始化延迟工作项
  INIT_DELAYED_WORK(&test_workqueue_work, test_work);  
  // 提交延迟工作项到自定义工作队列
  queue_delayed_work(test_workqueue, &test_workqueue_work, 3 * HZ); 
  cancel_delayed_work_sync(&test_workqueue_work); // 取消延迟工作项

猜你喜欢

转载自blog.csdn.net/xxxx123041/article/details/134148097