SylixOS 不同容器(ECS)间使用信号量同步方案

1、概述

      在 SylixOS 容器版本中由于容器间存在命名空间隔离的问题因此无法直接使用信号量进行同步操作,这在某些场合下可能无法完成实际需求,如共享内存通信时。本文介绍一种在容器间实现信号量同步功能的解决方案。

2、解决方案

      此解决方案思路是在 SylixOS 标准信号量的基础上封装一层字符设备,在内核层创建信号量并提供相关接口使容器内的 APP 可以通过字符设备接口获取内核信号量句柄,再通过标准信号量 API 进行操作。实现不同容器间的 APP 同步操作。基本框架如下图所示。

 

3、代码

字符设备:

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                SylixOS(TM)  LW : long wing
**
**                               Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: semc.c
**
** 创   建   人: Wang.Jingshi (王京石)
**
** 文件创建日期: 2021 年 07 月 13 日
**
** 描        述: 信号量设备(用于容器间资源同步)
*********************************************************************************************************/
#define  __SYLIXOS_KERNEL
#include <SylixOS.h>
#include <linux/compat.h>
#include <sys/ioccom.h>
#include "semc.h"
/*********************************************************************************************************
  设备结构
*********************************************************************************************************/
struct __semc_dev {
    LW_DEV_HDR                  SEMC_devhdr;                            /*  设备头                      */
    LW_LIST_LINE_HEADER         SEMC_fdNodeHeader;                      /*  文件节点链表头              */
    LW_HANDLE                   SEMC_handle;                            /*  信号量句柄                  */
    ULONG                       SEMC_ulInitCounter;                     /*  信号量初值                  */
    ULONG                       SEMC_ulMaxCounter;                      /*  信号量最大值                */
    ULONG                       SEMC_ulOption;                          /*  信号量选项                  */
};
typedef struct __semc_dev  __SEMC_DEV;
typedef __SEMC_DEV        *__PSEMC_DEV;
/*********************************************************************************************************
  全局变量
*********************************************************************************************************/
static __SEMC_DEV    _G_semcDev;                                        /*  信号量设备                  */
static INT           _G_iSemcDrvNum = 0;                                /*  信号量设备主设备号          */
/*********************************************************************************************************
** 函数名称: __semcOpen
** 功能描述: 打开 SEMC 设备
** 输  入  : pDev         设备
**           pcName       设备名字
**           iFlags       标志
**           iMode        模式
** 输  出  : NONE
** 返  回  : ERROR_CODE
*********************************************************************************************************/
static LONG  __semcOpen (__PSEMC_DEV  pDev, CHAR  *pcName, INT  iFlags, INT  iMode)
{
    BOOL         bIsNew;
    PLW_FD_NODE  pFdNode = LW_NULL;

    if (LW_NULL == pcName) {                                            /*  设备名称为空时,出错        */
        _ErrorHandle(ERROR_IO_NO_DEVICE_NAME_IN_PATH);

         return  (PX_ERROR);
    } else {                                                            /*  增加一个设备                */
        pFdNode = API_IosFdNodeAdd(&pDev->SEMC_fdNodeHeader,
                                   (dev_t)pDev,
                                   0,
                                   iFlags,
                                   iMode,
                                   0,
                                   0,
                                   0,
                                   LW_NULL,
                                   &bIsNew);
        if (LW_NULL == pFdNode) {                                       /*  判断节点是否为空            */
            printk(KERN_ERR "[semc] failed to add fd node.\n");

            return  (PX_ERROR);
        }

        if (LW_DEV_INC_USE_COUNT(&pDev->SEMC_devhdr) == 1) {
            CHAR cName[64];

            snprintf(cName, sizeof(cName), "dev_%s", pcName);
            pDev->SEMC_handle = API_SemaphoreCCreate(cName,
                                                     pDev->SEMC_ulInitCounter,
                                                     pDev->SEMC_ulMaxCounter,
                                                     pDev->SEMC_ulOption,
                                                     LW_NULL);
            if (pDev->SEMC_handle == LW_OBJECT_HANDLE_INVALID) {
                printk(KERN_ERR "[semc] semaphore create failded.\n");
                goto  __error;
            }
        }
    }

    return  ((LONG)pFdNode);

__error:
    LW_DEV_DEC_USE_COUNT(&pDev->SEMC_devhdr);
    if (pFdNode) {
        API_IosFdNodeDec(&pDev->SEMC_fdNodeHeader, pFdNode, LW_NULL);
    }

    return  ((LONG)LW_NULL);
}
/*********************************************************************************************************
** 函数名称: __semcClose
** 功能描述: SEMC 设备关闭
** 输  入  : pFdentry     文件结构
** 输  出  : NONE
** 返  回  : ERROR_CODE
*********************************************************************************************************/
static INT  __semcClose (PLW_FD_ENTRY  pFdentry)
{
    __PSEMC_DEV  pDev     = LW_NULL;
    PLW_FD_NODE  pfdNode  = LW_NULL;

    if (!pFdentry) {
        return  (PX_ERROR);
    }

    pDev    = (__PSEMC_DEV)pFdentry->FDENTRY_pdevhdrHdr;
    pfdNode = (PLW_FD_NODE)pFdentry->FDENTRY_pfdnode;
    if (pfdNode) {
        if (PX_ERROR == API_IosFdNodeDec(&pDev->SEMC_fdNodeHeader, pfdNode, LW_NULL)) {
                                                                        /*  是否成功删除节点            */
            return  (PX_ERROR);
        }

        if (LW_DEV_DEC_USE_COUNT(&pDev->SEMC_devhdr) == 0) {
            if (pDev->SEMC_handle) {
                API_SemaphoreCDelete(&pDev->SEMC_handle);
                pDev->SEMC_handle = LW_OBJECT_HANDLE_INVALID;
            }
        }
    }

    return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: __semcIoctl
** 功能描述: SEMC ioctl 操作接口
** 输  入  : pFdEntry      文件结构
**           iCmd          命令
**           lArg          参数
** 输  出  : NONE
** 返  回  : ERROR_CODE
*********************************************************************************************************/
static INT  __semcIoctl (PLW_FD_ENTRY  pFdentry, INT  iCmd, PVOID  plArg)
{
    __PSEMC_DEV  pDev = LW_NULL;

    if (LW_NULL == pFdentry) {
        return  (PX_ERROR);
    }
    pDev = (__PSEMC_DEV)pFdentry->FDENTRY_pdevhdrHdr;

    switch (iCmd) {

    case SEMC_CMD_GET_HANDLE:
        if (plArg) {
            *(LW_HANDLE *)plArg = pDev->SEMC_handle;
        }
        break;

    default:
        return  (PX_ERROR);
    }

    return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: semcDrvInstall
** 功能描述: 安装 SEMC 驱动
** 输  入  : NONE
** 输  出  : NONE
** 返  回  : ERROR_CODE
*********************************************************************************************************/
INT  semcDrvInstall (VOID)
{
    struct file_operations  fileopFileOP;

    if (_G_iSemcDrvNum) {                                               /*  主设备号是否被注册          */
        return  (ERROR_NONE);
    }

    lib_memset(&fileopFileOP, 0, sizeof(struct file_operations));

    fileopFileOP.owner     = THIS_MODULE;
    fileopFileOP.fo_create = __semcOpen;
    fileopFileOP.fo_open   = __semcOpen;
    fileopFileOP.fo_close  = __semcClose;
    fileopFileOP.fo_ioctl  = __semcIoctl;

    _G_iSemcDrvNum = iosDrvInstallEx2(&fileopFileOP, LW_DRV_TYPE_NEW_1);/*  注册设备驱动程序            */
    if (PX_ERROR == _G_iSemcDrvNum) {
        printk(KERN_ERR "[semc] DrvInstall failed.\r\n");

        return  (PX_ERROR);
    }

    DRIVER_LICENSE(_G_iSemcDrvNum, "Dual BSD/GPL->Ver 1.0");
    DRIVER_AUTHOR(_G_iSemcDrvNum, "WangJingshi");
    DRIVER_DESCRIPTION(_G_iSemcDrvNum, "semc driver.");

    return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: semcDevCreate
** 功能描述: 创建 SEMC 设备
** 输  入  : cpcName         设备名称
**           ulInitCounter   信号量初值
**           ulMaxCounter    信号量最大值
**           ulOption        信号量选项
** 输  出  : NONE
** 返  回  : ERROR_CODE
*********************************************************************************************************/
INT  semcDevCreate (CPCHAR  cpcName, ULONG  ulInitCounter, ULONG  ulMaxCounter, ULONG  ulOption)
{
    if (!cpcName) {
        printk(KERN_ERR "[semc] dev name invalid\n");
        return  (PX_ERROR);
    }
    /*
     * 信号量配置
     */
    _G_semcDev.SEMC_ulInitCounter  = ulInitCounter;
    _G_semcDev.SEMC_ulMaxCounter   = ulMaxCounter;
    _G_semcDev.SEMC_ulOption       = ulOption;
    /*
     *  向系统添加一个设备
     */
    if (ERROR_NONE != API_IosDevAddEx(&_G_semcDev.SEMC_devhdr, cpcName, _G_iSemcDrvNum, DT_CHR)) {
        printk(KERN_ERR "[semc] dev add failed.\n");
        _ErrorHandle(ERROR_SYSTEM_LOW_MEMORY);

        return  (PX_ERROR);
    }

    _ErrorHandle(ERROR_NONE);

    return  (ERROR_NONE);
}
/*********************************************************************************************************
  END
*********************************************************************************************************/

Demo:

#include <stdio.h>
#include "sys/ioctl.h"

#define SEMC_CMD_GET_HANDLE    _IOR('c', 1, LW_HANDLE)                  /*  获取信号量句柄              */

int main (int argc, char **argv)
{
    int        fd;
    LW_HANDLE  semc = LW_OBJECT_HANDLE_INVALID;
    INT        iError;
    INT        i    = 0;

    printf("1\n");

    fd = open("/dev/semc0", O_RDWR);
    if (fd < 0) {
        printf("open semc dev error.\n");
        return  PX_ERROR;
    }

    printf("fd = %d\n", fd);

    if (ioctl(fd, SEMC_CMD_GET_HANDLE, &semc) < 0 || semc == LW_OBJECT_HANDLE_INVALID ) {
        printf("get semc handle error.\n");
        return  PX_ERROR;
    }

    printf("semc = %d", semc);

    while (1) {
        iError = Lw_SemaphoreC_Wait(semc, LW_OPTION_WAIT_INFINITE);
        if (iError != ERROR_NONE) {
            printf("get semc handle error.iError = %d  errno = %d\n", iError, errno);
            return  PX_ERROR;
        }

        printf("semc wait... %d\n", i++);
        sleep(1);
        printf("semc post\n");

        Lw_SemaphoreC_Post(semc);

        sleep(1);
    }


    close(fd);

    return  (0);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

stone8761

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值