C 语言中实现环形缓冲区
1.实现代码:
#include
#include
#include
#include
#include
#defineBUFFSIZE1024*1024
#definemin(x,y)((x)<(y)?(x):(y))
pthread_mutex_tlock=PTHREAD_MUTEX_INITIALIZER;
structcycle_buffer{
unsignedchar*buf;
unsignedintsize;
unsignedintin;
unsignedintout;
pthread_mutex_tlock;
};
staticstructcycle_buffer*fifo=NULL;
staticintinit_cycle_buffer(void)
{
intsize=BUFFSIZE,ret;
ret=size&(size-1);
if(ret)
returnret;
fifo=(structcycle_buffer*)malloc(sizeof(structcycle_buffer));
if(!fifo)
return-1;
memset(fifo,0,sizeof(structcycle_buffer));
fifo->size=size;
fifo->in=fifo->out=0;
pthread_mutex_init(&fifo->lock,NULL);
fifo->buf=(unsignedchar*)malloc(size);
if(!fifo->buf)
free(fifo);
else
memset(fifo->buf,0,size);
return0;
}
unsignedintfifo_get(unsignedchar*buf,unsignedintlen)
{
unsignedintl;
len=min(len,fifo->in-fifo->out);
l=min(len,fifo->size-(fifo->out&(fifo->size-1)));
memcpy(buf,fifo->buf+(fifo->out&(fifo->size-1)),l);
memcpy(buf+l,fifo->buf,len-l);
fifo->out+=len;
returnlen;
}
unsignedintfifo_put(unsignedchar*buf,unsignedintlen)
{
unsignedintl;
len=min(len,fifo->size-fifo->in+fifo->out);
l=min(len,fifo->size-(fifo->in&(fifo->size-1)));
memcpy(fifo->buf+(fifo->in&(fifo->size-1)),buf,l);
memcpy(fifo->buf,buf+l,len-l);
fifo->in+=len;
returnlen;
}
staticvoid*thread_read(void*arg)
{
charbuf[1024];
unsignedintn;
pthread_detach(pthread_self());
for(;;){
memset(buf,0,sizeof(buf));
pthread_mutex_lock(&fifo->lock);
n=fifo_get(buf,sizeof(buf));
pthread_mutex_unlock(&fifo->lock);
write(STDOUT_FILENO,buf,n);
}
printf("nnafterthread_read:%snn",buf);
returnNULL;
}
staticvoid*thread_write(void*arg)
{
unsignedcharbuf[]="helloworld";
pthread_detach(pthread_self());
for(;;){
pthread_mutex_lock(&fifo->lock);
fifo_put(buf,strlen(buf));
pthread_mutex_unlock(&fifo->lock);
}
returnNULL;
}
intmain(void)
{
intret;
pthread_twtid,rtid;
ret=init_cycle_buffer();
if(ret==-1)
returnret;
pthread_create(&wtid,NULL,thread_write,NULL);
pthread_create(&rtid,NULL,thread_read,NULL);
pthread_exit(NULL);
return0;
}
1.buffer指向存放数据的缓冲区,size是缓冲区的大小,in是写指针下标,out是读指针下标,在len和(fifo->size-fifo->in+fifo->out)之间取一个较小的值赋给len。注意,当(fifo->in==fifo->out+fifo->size)时,表示缓冲区已满,此时得到的较小值一定是0,后面实际写入的字节数也全为0。另一种边界情况是当len很大时(因为len是无符号的,负数对它来说也是一个很大的正数),这一句也能保证len取到一个较小的值,因为fifo->in总是大于等于fifo->out,所以后面的那个表达式的值不会超过fifo->size的大小把上一步决定的要写入的字节数len“切开”,这里又使用了一个技巧。注意:实际分配给fifo->buffer的字节数fifo->size,必须是2的幂,否则这里就会出错。既然fifo->size是2的幂,那么(fifo->size-1)也就是一个后面几位全为1的数,也就能保证(fifo->in&(fifo->size-1))总为不超过(fifo->size-1)的那一部分,和(fifo->in)%(fifo->size-1)的效果一样。
2.这样后面的代码就不难理解了,它先向fifo->in到缓冲区末端这一块写数据,如果还没写完,在从缓冲区头开始写入剩下的,从而实现了循环缓冲。最后,把写指针后移len个字节,并返回len。
3.从上面可以看出,fifo->in的值可以从0变化到超过fifo->size的数值,fifo->out也如此,但它们的差不会超过fifo->size。
以上就是环形缓冲区域的C语言实现详解,希望对大家有所帮助,谢谢支持!