鸿蒙轻内核M核源码分析系列十一 信号量Semaphore

信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务间同步或共享资源的互斥访问。一个信号量的数据结构中,通常有一个计数值,用于对有效资源数的计数,表示剩下的可被使用的共享资源数。以同步为目的的信号量和以互斥为目的的信号量在使用上存在差异。本文通过分析鸿蒙轻内核信号量模块的源码,掌握信号量使用上的差异。本文中所涉及的源码,以OpenHarmony LiteOS-M内核为例,均可以在开源站点https://gitee.com/openharmony/kernel_liteos_m 获取。


接下来,我们看下信号量的结构体,信号量初始化,信号量常用操作的源代码。

1、信号量结构体定义和常用宏定义

1.1 信号量结构体定义

在文件kernel\include\los_sem.h定义的信号量控制块结构体为LosSemCB,结构体源代码如下。信号量状态.semStat取值OS_SEM_UNUSEDOS_SEM_USED,其他成员变量的注释见注释部分。

typedef struct {
    UINT16 semStat;      /**< 信号量状态 */
    UINT16 semCount;     /**< 可用的信号量数量 */
    UINT16 maxSemCount;  /**< 可用的信号量最大数量 */
    UINT16 semID;        /**< 信号量Id */
    LOS_DL_LIST semList; /**< 阻塞在该信号量的任务链表 */
} LosSemCB;

1.2 信号量常用宏定义

系统支持创建多少信号量是根据开发板情况使用宏LOSCFG_BASE_IPC_SEM_LIMIT定义的,每一个信号量semIdUINT32类型的,取值为[0,LOSCFG_BASE_IPC_SEM_LIMIT),表示信号量池中各个的信号量的编号。

⑴处的宏表示二值信号量的最大值为1,⑵处、⑶处的宏表示信号量未使用、使用状态值。⑷处根据信号量阻塞任务双向链表中的链表节点指针ptr获取信号量控制块结构体指针。⑸处从信号量池中获取指定信号量semId对应的信号量控制块。

⑴    #define OS_SEM_BINARY_MAX_COUNT     1

⑵    #define OS_SEM_UNUSED               0

⑶    #define OS_SEM_USED                 1

⑷    #define GET_SEM_LIST(ptr) LOS_DL_LIST_ENTRY(ptr, LosSemCB, semList)

⑸    #define GET_SEM(semid) (((LosSemCB *)g_allSem) + (semid))

2、信号量初始化

信号量在内核中默认开启,用户可以通过宏LOSCFG_BASE_IPC_SEM进行关闭。开启信号量的情况下,在系统启动时,在kernel\src\los_init.c中调用OsSemInit()进行信号量模块初始化。
下面,我们分析下信号量初始化的代码。

⑴初始化双向循环链表g_unusedSemList,维护未使用的信号量池。⑵为信号量池申请内存,如果申请失败,则返回错误。⑶循环每一个信号量进行初始化,为每一个信号量节点指定索引semID,把.semStat设置为未使用OS_SEM_UNUSED,并执行⑷把信号量节点插入未使用信号量双向链表g_unusedSemList

LITE_OS_SEC_TEXT_INIT UINT32 OsSemInit(VOID)
{
    LosSemCB *semNode = NULL;
    UINT16 index;

⑴  LOS_ListInit(&g_unusedSemList);

    if (LOSCFG_BASE_IPC_SEM_LIMIT == 0) {
        return LOS_ERRNO_SEM_MAXNUM_ZERO;
    }

⑵  g_allSem = (LosSemCB *)LOS_MemAlloc(m_aucSysMem0, (LOSCFG_BASE_IPC_SEM_LIMIT * sizeof(LosSemCB)));
    if (g_allSem == NULL) {
        return LOS_ERRNO_SEM_NO_MEMORY;
    }

⑶  for (index = 0; index < LOSCFG_BASE_IPC_SEM_LIMIT; index++) {
        semNode = ((LosSemCB *)g_allSem) + index;
        semNode->semID = index;
        semNode->semStat = OS_SEM_UNUSED;
⑷      LOS_ListTailInsert(&g_unusedSemList, &semNode->semList);
    }
    return LOS_OK;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值