SylixOS 块消息缓冲区

 1. 引入

本节介绍的内容原理很简单,就是著名的环形缓冲区,关于环形缓冲区的诸多介绍网上比比皆是,但是为了后面更加深入的学习SylixOS,我觉得有必要提一下这部分内容。在这里推荐一个开源库liblcthw网址是: https://github.com/zedshaw/liblcthw这个库用c代码实现了一些常用的数据结构,适合学习c语言的人看看。

接下来我们来学习一下SylixOS中块消息缓冲区实现上的一些技术细节。

2. 块消息缓冲区结构


这是从SylixOS源码中截取的一个图,从图中看块消息缓冲区结构中包含5个成员:

  • BM_pucBuffer指向消息缓冲区的首地址(也即环形缓冲区);
  • BM_stSize是消息缓冲区的总大小;

  • BM_stLeft是这个消息缓冲区中剩余的可用空间大小;

  • BM_pucPut向缓冲区中放入消息指针;

  • BM_pucGet从缓冲区中取出消息指针。

之所以称为块消息缓冲区是因为在缓冲区中的每个消息前都保留了2个字节的空间来保存消息的长度,这样一个完整的消息就包括了消息内容和消息长度。由此可见缓冲区的剩余空间不能小于2个字节,否则视为缓冲区满。同样SylixOS规定了缓冲区最小空间不能小于64字节。

3. 块消息缓冲区函数

下面我们简单的介绍缓冲区操作的一些函数:

PLW_BMSG  _bmsgCreate(size_t  stSize);
VOID      _bmsgDelete(PLW_BMSG  pbmsg);
INT       _bmsgPut(PLW_BMSG  pbmsg, CPVOID  pvMsg, size_t  stSize);
INT       _bmsgGet(PLW_BMSG  pbmsg, PVOID  pvMsg, size_t  stBufferSize);
VOID      _bmsgFlush(PLW_BMSG  pbmsg);
INT       _bmsgIsEmpty(PLW_BMSG  pbmsg);
INT       _bmsgIsFull(PLW_BMSG  pbmsg);
INT       _bmsgSizeGet(PLW_BMSG  pbmsg);
INT       _bmsgFreeByte(PLW_BMSG  pbmsg);
INT       _bmsgNBytes(PLW_BMSG  pbmsg);
INT       _bmsgNBytesNext(PLW_BMSG  pbmsg);

块消息缓冲区操作函数基本上就包括了上面的一组函数,我们重点看一下_bmsgPut 、_bmsgGet两个函数,这两个函数是缓冲区操作的核心,从名字看我们也可以想到_bmsgPut是往缓冲区中放入一条消息而_bmsgGet是从缓冲区中取出一条消息,这里值得我们注意的是放入的消息长度最大不得超过65536(也即2个字节的最大长度)下面是源码中部分片段:

INT  _bmsgPut (PLW_BMSG  pbmsg, CPVOID  pvMsg, size_t  stSize)
{
#define LW_BMSG_ADJUST_PUT() \
        if (pbmsg->BM_pucPut >= (pbmsg->BM_pucBuffer + pbmsg->BM_stSize)) { \
            pbmsg->BM_pucPut  = pbmsg->BM_pucBuffer; \
        }
    ...
    *pbmsg->BM_pucPut = (UCHAR)(stSize >> 8);         /*  保存两个字节长度信息     */
    pbmsg->BM_pucPut++;
    LW_BMSG_ADJUST_PUT();
    *pbmsg->BM_pucPut = (UCHAR)(stSize & 0xff);
    pbmsg->BM_pucPut++;
    LW_BMSG_ADJUST_PUT();
    ...
}

从源码中我们可以看出消息长度的低16位作为有效长度保存在了BM_pucPut前两个字节中。

宏LW_BMSG_ADJUST_PUT()实现了缓冲区的环形操作,其他的技术问题在这里就不再赘述了,都是一些缓冲区的常规处理问题了,具体可参考SylixOS源码。

4. 应用实例

下面的实例仅供说明SylixOS块消息缓冲区函数的使用方法,在SylixOS开发中不建议这样用,因为下面这段程序使用了许多SylixOS中不建议在这里用的函数或方法。同样这段程序也存在着许多问题,如互斥访问等。

#define __SYLIXOS_KERNEL
#include <SylixOS.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>

static LW_HANDLE sync_lock;
static char *msg = "Testing SylixOS bmsg.";
void *thread_putmsg (void *arg)
{
    PLW_BMSG pbmsg = (PLW_BMSG)arg;
_bmsgPut(pbmsg, msg, strlen(msg));

    API_SemaphoreBPost(sync_lock);
    while (1) {
        sleep(10);
    }
    return NULL;
}

void *thread_getmsg (void *arg)
{
    PLW_BMSG pbmsg = (PLW_BMSG)arg;
    char buf[64] = {0};

    API_SemaphoreBPend(sync_lock, LW_OPTION_WAIT_INFINITE);
    _bmsgGet(pbmsg, buf, strlen(msg));
    fprintf(stdout, "Recv msg: %s\n", buf);
    while (1) {
        sleep(10);
    }
    return NULL;
}

int main (int argc, char *argv[])
{
    PLW_BMSG pbmsg;
    pthread_t  tid1, tid2;

    pbmsg = _bmsgCreate(2048);
    if (!pbmsg) {
        fprintf(stderr, "bmsg create failed.\n");
        return -1;
    }
    sync_lock = API_SemaphoreBCreate("bmsg_sync", LW_FALSE, LW_OPTION_OBJECT_GLOBAL, LW_NULL);
    if (!sync_lock) {
        fprintf(stdout, "Create semaphore failed.\n");
        return  -1;
    }
    pthread_create(&tid1, NULL, thread_putmsg, (void *)pbmsg);
    pthread_create(&tid2, NULL, thread_getmsg, (void *)pbmsg);
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    return  (0);
}

(本节完)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值