环形缓冲区
来源:互联网 发布:java职业培训 编辑:程序博客网 时间:2024/04/28 05:54
1、什么是环形缓冲区
- 环形缓冲区,顾名思义就是一个环状的存储数据的区域,其空间使用数组进行构造(链表也可以)。环形缓冲区特点是读和写可以是分开的,写入数据之后可以先不去读取,等到需要读取的时候再去读取,并且数据一经读取之后下次就不能再去读取(当然也可以实现重复读取的效果,不过大多用作一次性读取),等于说是一次性的读取。
- 假设一个长度为256字节的数组,构建出一个环形缓冲区,当写操作进行到数组的第256项之后,再一次写入就会回到第0个进行写入;同样读操作是读取到数组的第256项时,再一次进行读取就会回到数组的第一项。是谓环形缓冲
2、环形缓冲区的作用
用作需要大量写入并且大量一次性读写的数据缓存区
比如视频的写入读取:在视频播放的时候需要不断的进行写入读取操作,而且数据一经读出就会显示出来,下次就不再需要已经读出的数据了。使用环形缓冲区可以满足这个要求,并且实现读写分别进行,而且节省了空间。
用作进程间通信,减少加锁开销
由于环形缓冲区的读写分开特性,当两个线程进行通信的时候,可以采用环形缓冲区进行交流,一个进程读取,一个进程写入,由于读写的位置不同,并不需要加锁进行并发控制,也就减少了锁的时间开销
3、程序编写测试(基于嵌入式linux的kmesg方式建立)
/* 使用printk函数打印调试信息,调试信息写到proc里面,形成一个环形缓冲区 */#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/proc_fs.h>#include <asm/uaccess.h>/* proc的文件结构体 */struct proc_dir_entry *entry;#define MAX_COUNT 1024 //缓冲区长度static char proc_buffer[MAX_COUNT]; //缓冲区数组static int empty_flag = 0; //是否为空,0表示为空static int last_r_pos = 0;static int mymsg_r = 0; //读位置static int mymsg_w = 0; //写位置/* 判断是否为空 */static int is_empty_mymsg(void){ if(((mymsg_w % MAX_COUNT) == (mymsg_r % MAX_COUNT)) && (empty_flag == 0)){ return 1; //Is empty } return 0; //Is not empty}/* 判断是否为满 */static int is_full_mymsg(void){ if(((mymsg_w % MAX_COUNT) == (mymsg_r % MAX_COUNT)) && (empty_flag != 0)){ return 1; //Is full } return 0; //Is not full}/* 读取一个字节 */static int read_onebyte_mymsg(char *buf_p){ if(is_empty_mymsg()){ return 0; //empty buffer can't read } *buf_p = proc_buffer[mymsg_r % MAX_COUNT]; mymsg_r = (mymsg_r + 1) % MAX_COUNT; empty_flag --; //每读取一个字节空标志减去1 return 1;}/* 写入一个字节 */static void write_onebyte_mymsg(char byte){ proc_buffer[mymsg_w % MAX_COUNT] = byte; if(is_full_mymsg()){ mymsg_r = (mymsg_r + 1) % MAX_COUNT; empty_flag --; } mymsg_w = (mymsg_w + 1) % MAX_COUNT; empty_flag ++; //每写入一个字节,空标志加一}/* 执行cat命令的时候会调用到,直到返回为空的时候cat才会返回 */static ssize_t printk_drv_read(struct file *f_name, char __user *buf, size_t cont, loff_t *lof){ char byte_to_user; cont = read_onebyte_mymsg(&byte_to_user); __put_user(byte_to_user, buf); return cont;}/* 自建打印函数,另带有往环形缓冲区里面写入数据的功能 */int myprintk(const char *fmt, ...){ va_list args; int r; va_start(args, fmt); r = vprintk(fmt, args); va_end(args); while(r --){ write_onebyte_mymsg(*fmt++); } return r;}EXPORT_SYMBOL(myprintk);const struct file_operations proc_mymsg_operations = { .owner = THIS_MODULE, .read = printk_drv_read,};static int printk_drv_init(void){ int i = 0; /* 打印测试 */ for(i = 0; i < MAX_COUNT; i++){ myprintk("F"); } /* 边界测试 */ for(i = 0; i < 5; i++){ myprintk("Y"); }// myprintk("Function printk_drv_init is running\n"); entry = create_proc_entry("mymsg", S_IRUSR, &proc_root); if (entry) entry->proc_fops = &proc_mymsg_operations;// myprintk("Function printk_drv_init finished\n"); return 0;}static void printk_drv_exit(void){ remove_proc_entry("mymsg", &proc_root);}module_init(printk_drv_init);module_exit(printk_drv_exit);MODULE_LICENSE("GPL");
4、测试结果
insmod myprintk.koFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFYYYYYcat /proc/mymsg FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFYYYYY//开始的5个F被清除掉了cat /proc/mymsg空
5、判断环形缓冲区的空或者满
设置额外的标志位
例如上面例子中的empty_flag,写的时候加上1,读的时候减去1,当满足读等于写并且empty_flag为0,则说明缓冲区空了。如果满足读等于写并且empty_flag不为0,说明缓冲区满了。
环形缓冲区始终空出一个值
例如:
/* 判断是否为空 */static int is_empty_mymsg(void){ //if(((mymsg_w % MAX_COUNT) == (mymsg_r % MAX_COUNT)) && (empty_flag == 0)){ if(((mymsg_w % MAX_COUNT) == (mymsg_r % MAX_COUNT))){ return 1; //Is empty } return 0; //Is not empty}/* 判断是否为满 */static int is_full_mymsg(void){ //if(((mymsg_w % MAX_COUNT) == (mymsg_r % MAX_COUNT)) && (empty_flag != 0)){ if((((mymsg_w + 1) % MAX_COUNT) == (mymsg_r % MAX_COUNT))){ return 1; //Is full } return 0; //Is not full}
这样就会导致在read位置前面的一个字节始终不能够写入数据,但是却很轻易的区分出来缓冲区是满还是空
0 0
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- 环形缓冲区
- PHP表单验证 -w3school PHP学习笔记
- XAudio2学习之音效相关结构体
- eterna框架-环境搭建
- DirectX 游戏开发
- 使用Spring 3的@value简化配置文件的读取
- 环形缓冲区
- VelocityTracker使用详解
- 对const object(const对象)的理解
- hdu 1823 Luck and Love 【二维线段树】
- ngui中scrollview的使用
- 单链表逆序
- 六大设计原则(1) 里氏替换原则
- java之Symmetric encryption techniques
- LeetCode——027