C 语言中实现环形缓冲区
1.实现代码:
#include #include #include #include #include #define BUFFSIZE 1024 * 1024 #define min(x, y) ((x) < (y) ? (x) : (y)) pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; struct cycle_buffer { unsigned char *buf; unsigned int size; unsigned int in; unsigned int out; pthread_mutex_t lock; }; static struct cycle_buffer *fifo = NULL; static int init_cycle_buffer(void) { int size = BUFFSIZE, ret; ret = size & (size - 1); if (ret) return ret; fifo = (struct cycle_buffer *) malloc(sizeof(struct cycle_buffer)); if (!fifo) return -1; memset(fifo, 0, sizeof(struct cycle_buffer)); fifo->size = size; fifo->in = fifo->out = 0; pthread_mutex_init(&fifo->lock, NULL); fifo->buf = (unsigned char *) malloc(size); if (!fifo->buf) free(fifo); else memset(fifo->buf, 0, size); return 0; } unsigned int fifo_get(unsigned char *buf, unsigned int len) { unsigned int l; 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; return len; } unsigned int fifo_put(unsigned char *buf, unsigned int len) { unsigned int l; 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; return len; } static void * thread_read(void *arg) { char buf[1024]; unsigned int n; 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("nnafter thread_read : %snn",buf); return NULL; } static void * thread_write(void *arg) { unsigned char buf[] = "hello world"; pthread_detach(pthread_self()); for (;;) { pthread_mutex_lock(&fifo->lock); fifo_put(buf, strlen(buf)); pthread_mutex_unlock(&fifo->lock); } return NULL; } int main(void) { int ret; pthread_t wtid, rtid; ret = init_cycle_buffer(); if (ret == -1) return ret; pthread_create(&wtid, NULL, thread_write, NULL); pthread_create(&rtid, NULL, thread_read, NULL); pthread_exit(NULL); return 0; }
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语言实现详解,希望对大家有所帮助,谢谢支持!
相关文章
- 这篇文章主要介绍了c++中system("pause")的作用和含义,非常不错,具有参考借鉴价值,需要的朋友参考下吧...2020-04-25
基于BootStrap Metronic开发框架经验小结【八】框架功能总体界面介绍
这篇文章主要介绍了基于BootStrap Metronic开发框架经验小结【八】框架功能总体界面介绍 的相关资料,需要的朋友可以参考下...2016-05-14- 这篇文章主要介绍了C# 16 进制字符串转 int的方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下...2020-06-25
InterlliJ IDEA2020新建java web项目找不到Static Web的解决
这篇文章主要介绍了InterlliJ IDEA2020新建java web项目找不到Static Web的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-09-02- 这篇文章主要介绍了C#判断一个字符串是否是数字或者含有某个数字的方法,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了C#类中static变量用法,实例分析了static变量使用技巧与相关注意事项,需要的朋友可以参考下...2020-06-25
- 这篇文章主要给大家介绍C# winform快捷键设置技巧,涉及到C winform快捷键相关知识,对C winform知识感兴趣的朋友可以参考下本篇文章...2020-06-25
- 这篇文章主要介绍了基于Ionic3实现选项卡切换并重新加载echarts,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-09-24
- 最近项目不多忙,于是抽点时间巩固下切换窗口问题,感兴趣的朋友跟着小编一起学习吧...2020-06-25
pytorch绘制并显示loss曲线和acc曲线,LeNet5识别图像准确率
今天小编就为大家分享一篇pytorch绘制并显示loss曲线和acc曲线,LeNet5识别图像准确率,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-05-02- 这篇文章主要为大家详细介绍了PC蓝牙通信C#代码实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
- 这篇文章主要介绍了C#实现带进度条的ListView 的相关资料,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了SpringMVC文件上传原理及实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-07-15
基于BootStrap Metronic开发框架经验小结【六】对话框及提示框的处理和优化
这篇文章主要介绍了基于BootStrap Metronic开发框架经验小结【六】对话框及提示框的处理和优化的相关知识,主要对比说明在Bootstrap开发中用到的这些技术要点,对此文感兴趣的朋友一起学习吧...2016-05-14- 这篇文章主要介绍了C#向线程中传递多个参数的解决方法(两种)的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下...2020-06-25
C# MVC模式中应该怎样区分应用程序逻辑(Controller层)和业务逻辑(Model层)?
这篇文章主要介绍了C# MVC模式中应该怎样区分应用程序逻辑(Controller层)和业务逻辑(Model层)?,这也小编做.NET项目时经常思考和让人混乱的一个问题,这篇文章写的挺好,一下清晰了许多,需要的朋友可以参考下...2020-06-25ShardingSphere jdbc集成多数据源的实现步骤
本文主要介绍了ShardingSphere jdbc集成多数据源的实现步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-10-21- 这篇文章介绍的是利用C#设置自定义文件图标,然后实现双击启动的功能,文章给出了示例代码,介绍的很详细,有需要的可以参考借鉴。...2020-06-25
基于BootStrap的Metronic框架实现页面链接收藏夹功能按钮移动收藏记录(使用Sortable进行拖动排序)
这篇文章主要介绍了基于BootStrap的Metronic框架实现页面链接收藏夹功能按钮移动收藏记录(使用Sortable进行拖动排序)的相关资料,非常不错,需要的朋友可以参考下...2016-09-01基于Bootstrap的Metronic框架实现页面链接收藏夹功能
本文给大家介绍基于Metronic的Bootstrap开发框架实现页面链接收藏夹功能,非常不错,具有参考借鉴价值,感兴趣的朋友一起学习吧...2016-09-01