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 0for(u32 i = 0; i < MAX_LEN; i++)printf("ring_buff[%d]:addr:0x%lx\n",i,share_mem->ring_data[i].addr);#endifmemset(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");elseprintf("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;
}