【ringbuff & share mem】

ringbuff 和share mem 结合实现PV操作

参考链接

https://juejin.cn/post/7113550346835722276
https://zhuanlan.zhihu.com/p/147826545

代码如下:

#include "rb.h"

int g_shmid = 0;

shm_buff * create_shm(int *smid)
{
    int id;
    shm_buff *share_mem = NULL;
    *smid = 0;

    id =  shmget((key_t)12345,sizeof(shm_buff),IPC_CREAT | IPC_EXCL | 0644);
    if(id == -1)
    {
        printf("rm exist share mem\n");
        system("sudo ipcrm -M 12345");
        id =  shmget((key_t)12345,sizeof(shm_buff),IPC_CREAT | IPC_EXCL | 0644);
        if(id == -1)
        {
            printf("creat share memory failed!\n");
            return NULL;
        }
    }
    share_mem = (shm_buff*)shmat(id,NULL,0);
    if(!share_mem)
    {
        printf("share mem is NULL\n");
        return NULL;
    }

    *smid = id;

    share_mem->end = 0;
    #if 0
    for(u32 i = 0; i < MAX_LEN; i++)
        printf("ring_buff[%d]:addr:0x%lx\n",i,share_mem->ring_data[i].addr);
    #endif
    memset(share_mem->ring_data, 0x0, sizeof(share_mem->ring_data));

    return share_mem;
}

void destroy_shm(int id, void* shm_buff)
{
    shmdt((const void*)shm_buff);
    shmctl(id, IPC_RMID, 0);
}
int main(int argc, char** argv)
{
    int ret = 0;
    int shmid = 0;

    shm_buff* sm = create_shm(&shmid);
    if(!sm || !shmid)
        return -1;

    g_shmid = shmid;
    ret = ring_buff_init(&sm->buff, sm->ring_data, sizeof(sm->ring_data), sizeof(entry));
    if(ret)
    {
        printf("ring_buff init fail ret:%d \n", ret);
        return ret;
    }

    int p = fork();
    if(p == 0)
    {
        printf("g_shmid:%d \n", g_shmid);
        sleep(1);
        for(;;)
        {
            if(sm->end && ring_buff_empty(&sm->buff))
                break;

            if(!ring_buff_empty(&sm->buff))
            {
                entry rdata;
                if(!ring_buff_read(&sm->buff, &rdata, 1))
                    printf("buff is empty----------\n");
                else
                    printf("data.addr:0x%lx size:0x%lx\n", rdata.addr, rdata.size);
            }else
            {
                //printf("wait p write data ...\n");
                //sleep(1);
            }

        }
        printf("read all done\n");
        //destroy_shm(shmid, sm);
    }else{
        int c = 0;
        printf("g_shmid:%d \n", g_shmid);
        for(int c = 0; c < 0x30;c++)
        {

            if(!ring_buff_full(&sm->buff))
            {
                entry data;
                data.addr = c;
                data.size = 4;
                if(!ring_buff_write(&sm->buff, &data, 1))
                {
                    printf("buff is full-----------------\n");
                }
            }else
            {
                printf("buff full wait c read data ...\n");
                sleep(1);
            }
        }
        sm->end = 1;
        sleep(2);
    }
}

头文件

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>

#define u32 unsigned int
#define u64 unsigned long

#define MAX_LEN 0x10
#define MIN(a, b) ((a) < (b) ? (a) : (b))

typedef struct entry_t
{
    u64 addr;
    u64 size;
}entry;

struct ring_buff {
    volatile unsigned int   in;
    volatile unsigned int   out;
    volatile unsigned int   mask;
    volatile unsigned int   esize;
    volatile unsigned int   lock;
    void        *data;
};

typedef struct shm_buff_t
{
    volatile unsigned int end;
    struct ring_buff buff;
    entry  ring_data[MAX_LEN];
}shm_buff;

static inline void ring_buff_lock(struct ring_buff *buff)
{
    while(buff->lock);
    buff->lock = 1;
}

static inline void ring_buff_unlock(struct ring_buff *buff)
{
    buff->lock = 0;
}

static inline unsigned int ring_buff_len(struct ring_buff *buff)
{
    return buff->in - buff->out;
}

static bool ring_buff_empty(struct ring_buff *buff)
{
    ring_buff_lock(buff);
    unsigned int l = ring_buff_len(buff);
    ring_buff_unlock(buff);

    return (l == 0) ? true:false;
}
static bool ring_buff_full(struct ring_buff *buff)
{
    ring_buff_lock(buff);
    unsigned int l = ring_buff_len(buff);
    ring_buff_unlock(buff);

    return l == (buff->mask + 1) ? true:false;
}

static inline unsigned int ring_buff_unused(struct ring_buff *buff)
{
    return (buff->mask + 1) - (buff->in - buff->out);
}

static int ring_buff_init(struct ring_buff *buff, void *buffer,
        unsigned int size, size_t esize)
{
    size /= esize;

    buff->in = 0;
    buff->out = 0;
    buff->lock = 0;
    buff->esize = esize;
    buff->data = buffer;

    if (size < 2) {
        buff->mask = 0;
        return -1;
    }

    buff->mask = size - 1;
    return 0;
}

static void ring_buff_copy_in(struct ring_buff *buff, const void *src,
        unsigned int len, unsigned int off)
{
    unsigned int size = buff->mask + 1;
    unsigned int esize = buff->esize;
    unsigned int l;

    off &= buff->mask;
    if (esize != 1) {
        off *= esize;
        size *= esize;
        len *= esize;
    }
    l = MIN(len, size - off);

    memcpy(buff->data + off, src, l);
    memcpy(buff->data, src + l, len - l);
    /*
     * make sure that the data in the buff is up to date before
     * incrementing the buff->in index counter
     */
    //smp_wmb();
}
static unsigned int ring_buff_write(struct ring_buff *buff,
        const void *buf, unsigned int len)
{
    unsigned int l;

    ring_buff_lock(buff);
    l = ring_buff_unused(buff);
    if (len > l)
        len = l;

    if(!len)
        return 0;

    ring_buff_copy_in(buff, buf, len, buff->in);
    buff->in += len;
    ring_buff_unlock(buff);

    return len;
}

static void ring_buff_copy_out(struct ring_buff *buff, void *dst,
        unsigned int len, unsigned int off)
{
    unsigned int size = buff->mask + 1;
    unsigned int esize = buff->esize;
    unsigned int l;

    off &= buff->mask;
    if (esize != 1) {
        off *= esize;
        size *= esize;
        len *= esize;
    }
    l = MIN(len, size - off);

    memcpy(dst, buff->data + off, l);
    memcpy(dst + l, buff->data, len - l);
    /*
     * make sure that the data is copied before
     * incrementing the buff->out index counter
     */
    //smp_wmb();
}

static unsigned int ring_buff_out_peek(struct ring_buff *buff,
        void *buf, unsigned int len)
{
    unsigned int l;

    l = ring_buff_len(buff);
    if(!l)
        return 0;

    if (len > l)
        len = l;

    ring_buff_copy_out(buff, buf, len, buff->out);
    return len;
}
static unsigned int ring_buff_read(struct ring_buff *buff,
        void *buf, unsigned int len)
{
    ring_buff_lock(buff);
    len = ring_buff_out_peek(buff, buf, len);
    buff->out += len;
    ring_buff_unlock(buff);

    return len;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值