SylixOS 下的工作队列

1、引言

1.1、工作队列的核心概念

  工作队列(Workqueue)是 Linux 内核提供的一种异步执行机制,它允许内核开发者将任务推迟执行或分配到其他线程处理。其核心架构由三个关键组件构成:

  • 工作项(Work):描述待执行任务的数据结构,包含要执行的函数及其参数
  • 工作队列(Workqueue):用于存放工作项的队列容器
  • 工作者(Worker):负责执行工作队列中任务的独立内核线程

1.2、工作机制与特点

  工作队列的运行遵循以下机制:

  • 当工作项被加入队列时,空闲的工作者线程会被唤醒
  • 工作者按 FIFO 顺序依次执行队列中的工作项函数
  • 队列为空时,工作者线程进入空闲状态(阻塞状态)

1.3、典型应用场景

  工作队列特别适用于以下情况:

  • 中断处理:将中断服务程序(上半部)中的复杂逻辑推迟到工作队列(下半部)执行
  • 耗时操作:执行可能阻塞或需要调度的长耗时任务

  这种机制有效平衡了系统响应性与任务复杂性,是 Linux 内核异步编程的重要基础设施。

2、SylixOS 下的内核工作队列

  内核工作队列(JobQueue)位于内核文件 libsylixos/SylixOS/kernel/core/_JobQueue.c 中,是纯粹的针对工作队列对象的一些操作集合,供内核使用,系统工作队列和网络工作队列都是基于内核工作队列实现的。

  内核工作队列本质上是基于数组实现的,同时使用了自旋锁进行过程保护和使用了信号量进行资源同步。实现过程比较简单,可以看源码直接分析。

2.1 创建工作队列

/*********************************************************************************************************
** 函数名称: _JobQueueCreate
** 功能描述: 创建一个工作队列
** 输 入  : uiQueueSize       队列大小
**           bNonBlock         执行函数是否为非阻塞方式
** 输 出  : 工作队列控制块
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
PLW_JOB_QUEUE  _jobQueueCreate (UINT uiQueueSize, BOOL bNonBlock)
{
    PLW_JOB_QUEUE pjobq;
    /* 初始化一个工作队列、分配内存空间 */
    pjobq = (PLW_JOB_QUEUE)__KHEAP_ALLOC((size_t)(sizeof(LW_JOB_QUEUE) + 
                                         (uiQueueSize * sizeof(LW_JOB_MSG))));
    if (pjobq == LW_NULL) {
        _DebugHandle(__ERRORMESSAGE_LEVEL, "kernel low memory.\r\n");
        _ErrorHandle(ERROR_KERNEL_LOW_MEMORY);
        return  (LW_NULL);
    }
    
    pjobq->JOBQ_pjobmsgQueue = (PLW_JOB_MSG)(pjobq + 1);
    pjobq->JOBQ_uiIn         = 0;
    pjobq->JOBQ_uiOut        = 0;
    pjobq->JOBQ_uiCnt        = 0;
    pjobq->JOBQ_uiSize       = uiQueueSize;
    pjobq->JOBQ_ulLost       = 0;
    
    /* 这里的同步信号量,可以确保工作队列线程在空闲时,处于阻塞状态,不占用系统资源 */
    if (bNonBlock == LW_FALSE) {
        pjobq->JOBQ_ulSync = API_SemaphoreBCreate("job_sync", LW_FALSE, LW_OPTION_OBJECT_GLOBAL, LW_NULL);
        if (pjobq->JOBQ_ulSync == LW_OBJECT_HANDLE_INVALID) {
            __KHEAP_FREE(pjobq);
            return  (LW_NULL);
        }
    } else {
        pjobq->JOBQ_ulSync = LW_OBJECT_HANDLE_INVALID;
    }
    
    LW_SPIN_INIT(&pjobq->JOBQ_slLock);
    
    return  (pjobq);
}

2.2 添加工作

/*********************************************************************************************************
** 函数名称: _JobQueueAdd
** 功能描述: 添加一个工作到工作队列
** 输 入  : pjobq         工作队列控制块
**           pfunc         要执行的函数
**           pvArg0 ~ 5    函数参数
** 输 出  : ERROR
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
ULONG  _jobQueueAdd (PLW_JOB_QUEUE pjobq,
                     VOIDFUNCPTR   pfunc,
                     PVOID         pvArg0,
                     PVOID         pvArg1,
                     PVOID         pvArg2,
                     PVOID         pvArg3,
                     PVOID         pvArg4,
                     PVOID         pvArg5)
{
    INTREG           iregInterLevel;
    PLW_JOB_MSG      pjobmsg;
    
    LW_SPIN_LOCK_QUICK(&pjobq->JOBQ_slLock, &iregInterLevel);
    /* 工作队列是有大小限制的。在队列初始化时,设置队列大小 */
    if (pjobq->JOBQ_uiCnt == pjobq->JOBQ_uiSize) {
        pjobq->JOBQ_ulLost++;
        LW_SPIN_UNLOCK_QUICK(&pjobq->JOBQ_slLock, iregInterLevel);
        _DebugHandle(__ERRORMESSAGE_LEVEL, "job message lost.\r\n");
        return  (ENOSPC);
    }
    
    /* 工作项,实际上就是一个函数 pfunc 和其入参 */
    pjobmsg                 = &pjobq->JOBQ_pjobmsgQueue[pjobq->JOBQ_uiIn];
    pjobmsg->JOBM_pfuncFunc = pfunc;
    pjobmsg->JOBM_pvArg[0]  = pvArg0;
    pjobmsg->JOBM_pvArg[1]  = pvArg1;
    pjobmsg->JOBM_pvArg[2]  = pvArg2;
    pjobmsg->JOBM_pvArg[3]  = pvArg3;
    pjobmsg->JOBM_pvArg[4]  = pvArg4;
    pjobmsg->JOBM_pvArg[5]  = pvArg5;
    
    if (pjobq->JOBQ_uiIn == (pjobq->JOBQ_uiSize - 1)) {
        pjobq->JOBQ_uiIn =  0;
    } else {
        pjobq->JOBQ_uiIn++;
    }
    
    pjobq->JOBQ_uiCnt++;
    LW_SPIN_UNLOCK_QUICK(&pjobq->JOBQ_slLock, iregInterLevel);
    
    /* 尝试唤醒工作队列(工作者) */
    if (pjobq->JOBQ_ulSync) {
        API_SemaphoreBPost(pjobq->JOBQ_ulSync);
    }
    
    return  (ERROR_NONE);
}

2.3 执行工作

/*********************************************************************************************************
** 函数名称: _jobQueueExec
** 功能描述: 执行工作队列中的工作
** 输 入  : pjobq         工作队列控制块
**           ulTimeout     等待超时时间
** 输 出  : 不为 ERROR_NONE 表示超时
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
ULONG  _jobQueueExec (PLW_JOB_QUEUE pjobq, ULONG  ulTimeout)
{
    INTREG          iregInterLevel;
    PLW_JOB_MSG     pjobmsg;
    LW_JOB_MSG      jobmsgRun;
    
    if (pjobq->JOBQ_ulSync) {
        for (;;) {
        	/* 这里是工作者阻塞的根源 */
            if (API_SemaphoreBPend(pjobq->JOBQ_ulSync, ulTimeout)) {
                return  (ERROR_THREAD_WAIT_TIMEOUT);
            }
            LW_SPIN_LOCK_QUICK(&pjobq->JOBQ_slLock, &iregInterLevel);
            if (pjobq->JOBQ_uiCnt) {
                break;
            }
            LW_SPIN_UNLOCK_QUICK(&pjobq->JOBQ_slLock, iregInterLevel);
        }
    } else {
        LW_SPIN_LOCK_QUICK(&pjobq->JOBQ_slLock, &iregInterLevel);
    }
    
    /* 从这里可以看到,工作者每被唤醒一次,会尝试把工作队列里面的所有工作项都完成 */
    while (pjobq->JOBQ_uiCnt) {
        pjobmsg = &pjobq->JOBQ_pjobmsgQueue[pjobq->JOBQ_uiOut];
        LW_JOB_MSG_COPY(&jobmsgRun, pjobmsg);
        if (pjobq->JOBQ_uiOut == (pjobq->JOBQ_uiSize - 1)) {
            pjobq->JOBQ_uiOut =  0;
        } else {
            pjobq->JOBQ_uiOut++;
        }
        pjobq->JOBQ_uiCnt--;
        LW_SPIN_UNLOCK_QUICK(&pjobq->JOBQ_slLock, iregInterLevel);
        
        if (jobmsgRun.JOBM_pfuncFunc) {
            jobmsgRun.JOBM_pfuncFunc(jobmsgRun.JOBM_pvArg[0],
                                     jobmsgRun.JOBM_pvArg[1],
                                     jobmsgRun.JOBM_pvArg[2],
                                     jobmsgRun.JOBM_pvArg[3],
                                     jobmsgRun.JOBM_pvArg[4],
                                     jobmsgRun.JOBM_pvArg[5]);
        }
        
        LW_SPIN_LOCK_QUICK(&pjobq->JOBQ_slLock, &iregInterLevel);
    }
    LW_SPIN_UNLOCK_QUICK(&pjobq->JOBQ_slLock, iregInterLevel);
    
    return  (ERROR_NONE);
}

_jobQueueExec 通常会放到一个线程中。内核工作队列文件中并没有这个操作,通常由具体使用者去创建。

3、SylixOS 下的系统工作队列

  系统工作队列(Work Queue)是 SylixOS 提供的系统级接口,供驱动和应用层直接调用。

  系统工作队列底层实现其实分两部分,简单工作队列(simple work queue)和 延时工作队列(delay work queue)。

  • 简单工作队列由 __wqS 打头的函数簇实现,本质是基于内核工作队列并结合了执行线程创建、同步保护等相关操作实现
  • 延时工作队列由 __wqD 打头的函数簇实现,本质和内核工作队无关,是基于单向链表和等待唤醒链表实现的

  系统工作队列相比于内核工作队列,不仅提供了执行线程,还提供了延时执行的功能,更便于被直接调用,是一种系统级调用接口。内核工作队列提供的则是更基础的调用方法,是一种半成品。对于一些不适合直接使用系统工作队列的地方,可以在内核工作队列的基础上构造自己独享的工作队列模块,如网络接收处理和系统中断下半部执行等都是基于内核工作队列单独实现的。

  下面仅以简单工作队列为例讲解,延时工作队列具体内容,感兴趣的可以自行研究 SylixOS 源码。

3.1 创建工作队列

/*********************************************************************************************************
** 函数名称: __wqSExec
** 功能描述: 执行一次工作队列
** 输 入  : pwq          工作队列控制块
** 输 出  : NONE
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
static VOID  __wqSExec (PLW_WORK_QUEUE  pwq)
{
    _jobQueueExec(pwq->q.WQ_sq.SWQ_pjobQ, LW_OPTION_WAIT_INFINITE);
}
/*********************************************************************************************************
** 函数名称: __wqTask
** 功能描述: 工作队列服务线程
** 输 入  : pvArg        工作队列控制块
** 输 出  : NULL
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
static PVOID  __wqTask (PVOID  pvArg)
{
    PLW_WORK_QUEUE  pwq = (PLW_WORK_QUEUE)pvArg;
    
    for (;;) {
        switch (pwq->WQ_iType) {
        
        case LW_WQ_TYPE_S:
            __wqSExec(pwq);
            break;
            
        case LW_WQ_TYPE_D:
            __wqDExec(pwq);
            break;
            
        default:
            break;
        }
        
        if (pwq->WQ_bDelReq) {
            break;
        }
    }
    
    return  (LW_NULL);
}
/*********************************************************************************************************
** 函数名称: __wqSCreate
** 功能描述: 创建一个简单工作队列
** 输 入  : pwq           工作队列控制块
**           uiQSize       队列大小
** 输 出  : ERROR_CODE
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
static PLW_WORK_QUEUE  __wqSCreate (PLW_WORK_QUEUE  pwq, UINT  uiQSize)
{
    pwq->WQ_iType = LW_WQ_TYPE_S;
    pwq->q.WQ_sq.SWQ_pjobQ = _jobQueueCreate(uiQSize, LW_FALSE);
    if (pwq->q.WQ_sq.SWQ_pjobQ == LW_NULL) {
        return  (LW_NULL);
    }
    
    return  (pwq);
}
/*********************************************************************************************************
** 函数名称: API_WorkQueueCreate
** 功能描述: 创建一个工作队列
** 输 入  : pcName            队列名称
**           uiQSize           队列大小
**           bDelayEn          是否创建带有延迟执行功能的工作队列
**           ulScanPeriod      如果带有延迟选项, 此参数指定服务线程扫描周期.
**           pthreadattr       队列服务线程选项
** 输 出  : 工作队列句柄
** 全局变量: 
** 调用模块: 
** 注  意  : 如果不需要延迟执行功能, 则系统自动创建为简单工作队列, 内存占用量小, 执行效率高.

                                           API 函数
*********************************************************************************************************/
LW_API  
PVOID  API_WorkQueueCreate (CPCHAR                  pcName,
                            UINT                    uiQSize, 
                            BOOL                    bDelayEn, 
                            ULONG                   ulScanPeriod, 
                            PLW_CLASS_THREADATTR    pthreadattr)
{
    PLW_WORK_QUEUE         pwq;
    LW_CLASS_THREADATTR    threadattr;
    
    if (!uiQSize || (bDelayEn && !ulScanPeriod)) {
        _ErrorHandle(EINVAL);
        return  (LW_NULL);
    }
    
    pwq = (PLW_WORK_QUEUE)__KHEAP_ALLOC(sizeof(LW_WORK_QUEUE));
    if (pwq == LW_NULL) {
        _DebugHandle(__ERRORMESSAGE_LEVEL, "kernel low memory.\r\n");
        _ErrorHandle(ENOMEM);
        return  (LW_NULL);
    }
    lib_bzero(pwq, sizeof(LW_WORK_QUEUE));
    
    /* 这里区分是普通工作队列还是延迟工作队列 */
    if (bDelayEn) {
        if (__wqDCreate(pwq, uiQSize, ulScanPeriod) == LW_NULL) {
            __KHEAP_FREE(pwq);
            return  (LW_NULL);
        }
    
    } else {
    	/* 创建工作队列,调用创建内核工作队列接口 */
        if (__wqSCreate(pwq, uiQSize) == LW_NULL) {
            __KHEAP_FREE(pwq);
            return  (LW_NULL);
        }
    }
    
    if (pthreadattr) {
        threadattr = *pthreadattr;
    
    } else {
        threadattr = API_ThreadAttrGetDefault();
    }
    
    threadattr.THREADATTR_ulOption &= ~LW_OPTION_THREAD_DETACHED;
    threadattr.THREADATTR_ulOption |= LW_OPTION_OBJECT_GLOBAL;
    threadattr.THREADATTR_pvArg     = pwq;
    
    /*  创建用于执行工作队列的线程 __wqTask(工作者) */
    pwq->WQ_ulTask = API_ThreadCreate(pcName, __wqTask, &threadattr, LW_NULL);
    if (pwq->WQ_ulTask == LW_OBJECT_HANDLE_INVALID) {
        if (bDelayEn) {
            __wqDDelete(pwq);
        
        } else {
            __wqSDelete(pwq);
        }
        __KHEAP_FREE(pwq);
        return  (LW_NULL);
    }
    
    return  ((PVOID)pwq);
}

3.2 添加工作

/*********************************************************************************************************
** 函数名称: __wqSInsert
** 功能描述: 将一个工作插入到工作队列
** 输 入  : pwq          工作队列控制块
**           pfunc        执行函数
**           pvArg0 ~ 5   执行参数
** 输 出  : ERROR_CODE
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
static ULONG  __wqSInsert (PLW_WORK_QUEUE  pwq, 
                           VOIDFUNCPTR     pfunc, 
                           PVOID           pvArg0,
                           PVOID           pvArg1,
                           PVOID           pvArg2,
                           PVOID           pvArg3,
                           PVOID           pvArg4,
                           PVOID           pvArg5)
{
	/* 可以看到,这里是直接调用的内核工作队列 */
    return  (_jobQueueAdd(pwq->q.WQ_sq.SWQ_pjobQ,
                          pfunc, pvArg0, pvArg1, pvArg2,
                          pvArg3, pvArg4, pvArg5));
}
/*********************************************************************************************************
** 函数名称: API_WorkQueueInsert
** 功能描述: 将一个工作插入到工作队列
** 输 入  : pvWQ         工作队列句柄
**           ulDelay      最小延迟执行时间
**           pfunc        执行函数
**           pvArg0 ~ 5   执行参数
** 输 出  : ERROR_CODE
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API  
ULONG  API_WorkQueueInsert (PVOID           pvWQ, 
                            ULONG           ulDelay,
                            VOIDFUNCPTR     pfunc, 
                            PVOID           pvArg0,
                            PVOID           pvArg1,
                            PVOID           pvArg2,
                            PVOID           pvArg3,
                            PVOID           pvArg4,
                            PVOID           pvArg5)
{
    PLW_WORK_QUEUE  pwq = (PLW_WORK_QUEUE)pvWQ;
    ULONG           ulRet;
    
    if (!pwq) {
        _ErrorHandle(EINVAL);
        return  (EINVAL);
    }
    
    switch (pwq->WQ_iType) {
        
    case LW_WQ_TYPE_S:
        ulRet = __wqSInsert(pwq, pfunc, pvArg0, pvArg1, pvArg2,
                            pvArg3, pvArg4, pvArg5);
        break;
        
    case LW_WQ_TYPE_D:
        ulRet = __wqDInsert(pwq, ulDelay, pfunc, pvArg0, pvArg1, pvArg2,
                            pvArg3, pvArg4, pvArg5);
        break;
        
    default:
        _ErrorHandle(ENXIO);
        ulRet = ENXIO;
        break;
    }
    
    return  (ulRet);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值