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;
}