内核工作队列

更新时间:
2024-01-09
下载文档

内核工作队列

简介与原理

在内核代码中,经常希望将部分工作推迟到将来的某个时间执行,这样做的原因有很多,比如:

  • 在持有锁的情况下做耗时操作。
  • 希望将工作集中起来以获取批处理的性能。
  • 调用了可能导致睡眠的函数。

SylixOS 内核提供了一种机制来提供延迟执行的功能,即工作队列。工作队列是将操作延期执行的一种手段。工作队列可以把工作推后,交由一个内核线程去执行,并且工作队列是执行在进程上下文中,因此工作队列可以被重新调度和抢占甚至睡眠。

一个 SylixOS 工作队列必须要调用 API_WorkQueueCreate 函数创建之后才能使用,如果创建成功,API_WorkQueueCreate 函数将返回一个工作队列的句柄。

如果需要插入一个工作到工作队列中,可以调用 API_WorkQueueInsert 函数。

当一个工作队列使用完毕之后,应该调用 API_WorkQueueDelete 函数将其删除,SylixOS 会回收该工作队列占用的内核资源。

工作队列的应用

工作队列的创建

#include <SylixOS.h> 
PVOID  API_WorkQueueCreate (CPCHAR                  pcName,
                            UINT                    uiQSize, 
                            BOOL                    bDelayEn, 
                            ULONG                   ulScanPeriod, 
                            PLW_CLASS_THREADATTR    pthreadattr);

函数 API_WorkQueueCreate 原型分析:

  • 此函数成功返回工作队列句柄,失败返回 LW_NULL 并设置错误号。
  • pcName 参数是工作队列的名称。
  • uiQSize 参数是工作队列的大小。
  • bDelayEn 参数是工作队列的延迟执行功能选项。
  • ulScanPeriod 参数是当带有延迟执行选项时,指定服务线程的扫描周期。
  • pthreadattr 参数是队列服务线程选项。

工作队列的删除

#include <SylixOS.h> 
ULONG  API_WorkQueueDelete (PVOID  pvWQ);

函数 API_WorkQueueDelete 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回错误号。
  • pvWQ 参数是工作队列句柄。

向工作队列中插入一个工作

#include <SylixOS.h> 
ULONG  API_WorkQueueInsert (PVOID              pvWQ, 
                            ULONG              ulDelay,
                            VOIDFUNCPTR        pfunc, 
                            PVOID              pvArg0,
                            PVOID              pvArg1,
                            PVOID              pvArg2,
                            PVOID              pvArg3,
                            PVOID              pvArg4,
                            PVOID              pvArg5);

函数 API_WorkQueueInsert 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回错误号。
  • pvWQ 参数是工作队列句柄。
  • ulDelay 参数是最小延迟执行时间。
  • pfunc 参数是执行函数。
  • pvArg0 ~ pvArg5 参数是执行参数。 。

工作队列的清空

#include <SylixOS.h> 
ULONG  API_WorkQueueFlush (PVOID  pvWQ);

函数 API_WorkQueueFlush 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回错误号。
  • pvWQ 参数是工作队列句柄。

工作队列的状态获取

#include <SylixOS.h> 
ULONG  API_WorkQueueStatus (PVOID  pvWQ, UINT  *puiCount);

函数 API_WorkQueueStatus 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回错误号。
  • pvWQ 参数是工作队列句柄。
  • puiCount 参数是当前工作队列中的作业数量。

工作队列的应用场景有很多:比如需要在中断(下半部)里面要做很多的耗时操作,这时就可以把耗时的工作放到工作队列中。

以下程序展示了 SylixOS 工作队列的使用,加载此内核模块会创建了一个不带有延迟执行功能的 SylixOS 工作队列,然后向工作队列中插入了一个工作,卸载内核模块时删除工作队列。

#define  __SYLIXOS_KERNEL
#include <SylixOS.h>
#include <module.h>
PVOID  _G_pvWorkQueue;
static VOID  __workHandler (VOID)
{
    printk("work handler function.\n");
}
VOID  module_init (VOID)
{
    LW_CLASS_THREADATTR  threadattr;
    printk("WorkQueue_module init!\n");
    API_ThreadAttrBuild(&threadattr,
                        4 * LW_CFG_KB_SIZE,
                        LW_PRIO_NORMAL,
                        LW_OPTION_THREAD_STK_CHK,
                        LW_NULL);
    _G_pvWorkQueue = API_WorkQueueCreate("t_workqueue",
                                         10,
                                         FALSE,
                                         0,
                                         &threadattr);
    if (_G_pvWorkQueue == LW_NULL) {
        printk("WorkQueue create failed.\n");
        return;
    }
    API_WorkQueueInsert(_G_pvWorkQueue,
                        0,
                        __workHandler,
                        LW_NULL,
                        LW_NULL,
                        LW_NULL,
                        LW_NULL,
                        LW_NULL,
                        LW_NULL);
}
VOID  module_exit (VOID)
{
    API_WorkQueueDelete(_G_pvWorkQueue);
    printk("WorkQueue_module exit!\n");
}

在 SylixOS Shell 下装载模块:

#insmod ./WorkQueue.ko
WorkQueue_module init!
module WorkQueue.ko register ok, handle: 0x13338f0
work handler function.

在 SylixOS Shell 下卸载模块:

#rmmod  WorkQueue.ko
WorkQueue_module exit!
module /lib/modules/WorkQueue.ko unregister ok.
文档内容是否对您有所帮助?
有帮助
没帮助