缓冲池的重要性

1、背景

当一个服务端对外获取数据然后将自己获取的数据分发给客户端,但是在分发环节特别耗时导致外界向服务端请求去读,但是此时服务端并没有响应去读取外界数据,此时导致了外界请求端的缓存溢出,数据存在丢失的问题。

2、解决方式

这里的解决手段需要两步,第一提高服务端对外界的响应程度 (提高服务端线程的调度优先级),第二在服务端和分发的客户端端之间建立缓冲池。这里重点说缓冲池。

3、实际操作

这里介绍一个缓冲池(ringBuffer)的使用。

ringbuf.h

#ifndef _RINGBUFFER_H
#define _RINGBUFFER_H

struct ringbuffer { 
    void *data;
    unsigned int size;
    unsigned int read_pos;
    unsigned int write_pos;
};

struct ringbuffer *ringbuffer_create(unsigned int bytes);
void ringbuffer_destroy(struct ringbuffer *ring_buf);
void ringbuffer_reset(struct ringbuffer *ring_buf);
unsigned int ringbuffer_put(struct ringbuffer *ring_buf,const char *buf, unsigned int len);

unsigned int ringbuffer_get(struct ringbuffer *ring_buf,char *buf, unsigned int len);
ssize_t ringbuffer_from_dev(int fd, struct ringbuffer *ring_buf, unsigned int len);

unsigned int ringbuffer_is_empty(struct ringbuffer *ring_buf);
unsigned int ringbuffer_is_full(struct ringbuffer *ring_buf);

unsigned int ringbuffer_len(struct ringbuffer *ring_buf);
unsigned int ringbuffer_space_left(struct ringbuffer *ring_buf);

#endif
ringbuf.c

struct ringbuffer*  tmp_fifo;

//这里的 n 必须等于 为 2的次幂方
static inline __attribute__((const)) int is_power_of_2(unsigned long n)   
{
    return (n != 0 && ((n & (n - 1)) == 0));
}

// 创建初始化 ringBuffer 
struct ringbuffer *ringbuffer_create(unsigned int size)
{
    struct ringbuffer *ring_buf;

    if (!is_power_of_2(size)) {
        LOGE("The buffer size is must be power of 2!");
        errno = EINVAL;
        return NULL;
    }
    ring_buf = malloc(sizeof(*ring_buf));
    if (!ring_buf) {
        LOGE("malloc()");
        return NULL;
    }
    ring_buf->data = malloc(size);
    if (!ring_buf->data) {
        LOGE("malloc()");
        free(ring_buf);
        return NULL;
    }
    ring_buf->size = size;
    ring_buf->read_pos = 0;
    ring_buf->write_pos = 0;

    return ring_buf;
}

// 销毁释放 ringBuffer
void ringbuffer_destroy(struct ringbuffer *ring_buf)
{
    if (ring_buf) {
        if (ring_buf->data) {
            free(ring_buf->data);
            ring_buf->data = NULL;
        }
        free(ring_buf);
        ring_buf = NULL;
    }
}
//从 write_pos 位置向后写,尾部不够再从头部开始写
unsigned int ringbuffer_put(struct ringbuffer *ring_buf,const char *buffer, unsigned int len)
{
    unsigned int l;

    len = min(len, ring_buf->size - ring_buf->write_pos + ring_buf->read_pos);

    /* first put the data starting from write_pos to buffer end */
    l = min(len, ring_buf->size - (ring_buf->write_pos & (ring_buf->size - 1)));
    memcpy(ring_buf->data + (ring_buf->write_pos & (ring_buf->size - 1)), buffer, l);

    /* then put the rest (if any) at the beginning of the buffer */
    memcpy(ring_buf->data, buffer + l, len - l);

    ring_buf->write_pos += len;

    return len;
}
//从 read_pos 位置向后读,尾部不够再从头部开始读
unsigned int ringbuffer_get(struct ringbuffer *ring_buf,char *buffer, unsigned int len)
{
    unsigned int l;

    len = min(len, ring_buf->write_pos - ring_buf->read_pos);

    /* first get the data from ring_buf->read_pos until the end of the buffer */
    /* (ring_buf->read_pos & (ring_buf->size - 1)) 的含义是获取 read_pos在 size 中的位置。如果read_pos 大于 size表示已经读取一圈* eg ring_buf->size = 128  ring_buf->size - 1 =127  如果 ring_buf->read_pos=30 小于 127  那么就是0 轮回 30 ,如果 read_pos=150 大于 128  那么就是 1轮回 22 。ring_buf->size - (ring_buf->read_pos & (ring_buf->size - 1)) 算出的就是 从 read_pos 到 end buffer 的 大小*/
    
    l = min(len, ring_buf->size - (ring_buf->read_pos & (ring_buf->size - 1)));
    memcpy(buffer, ring_buf->data + (ring_buf->read_pos & (ring_buf->size - 1)), l);

    /* then get the rest (if any) from the beginning of the buffer */
    memcpy(buffer + l, ring_buf->data, len - l);

    ring_buf->read_pos += len;

    return len;
}

//清空 ringBuffer
void ringbuffer_reset(struct ringbuffer *ring_buf)
{
    ring_buf->write_pos = ring_buf->read_pos = 0;
}

//判断 ringBuffer 是否为空
unsigned int ringbuffer_is_empty(struct ringbuffer *ring_buf)
{
    return ring_buf->read_pos == ring_buf->write_pos;
}
//判断 ringBuffer 是否为满
unsigned int ringbuffer_is_full(struct ringbuffer *ring_buf)
{
    return ring_buf->size == ring_buf->write_pos -  ring_buf->read_pos;
}
//获取 ringBuffer 中有效数据的长度
unsigned int ringbuffer_len(struct ringbuffer *ring_buf)
{
    return ring_buf->write_pos -  ring_buf->read_pos;
}
//判断 ringBuffer 可用空间
unsigned int ringbuffer_space_left(struct ringbuffer *ring_buf)
{
    return ring_buf->size - ring_buf->write_pos + ring_buf->read_pos;
}
1、创建

tmp_fifo_size = 32 * 128; // 2的12次幂 4kb
tmp_fifo = ringbuffer_create(tmp_fifo_size); 

2、存放

pthread_mutex_lock (&mutex);
space_left = ringbuffer_space_left(tmp_fifo); //判断剩余空间
if(space_left < tmp_fifo_size/2) {
		LOGE("WARNING!!! left space in ringbuffer:%d", space_left);
}
if(space_left >= i2c_data_len) {
		ringbuffer_put(tmp_fifo, (const char*)&tmp_buf, i2c_data_len);
}
pthread_mutex_unlock(&mutex);

3、读取

pthread_mutex_lock (&mutex);
ringbuffer_is_empty(tmp_fifo); // 判断是否为空
size = ringbuffer_get(tmp_fifo, (char*)i2c_buf, i2c_data_len); //不为空 获取数据
pthread_mutex_unlock(&mutex);      

4、生产者消费者模型

生产者消费者模式浅析

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值