嵌入式 环形缓冲区的设计与实现
2016-01-14 09:31
429 查看
环形缓冲区是嵌入式系统中十分重要的一种数据结构,比如在一个视频处理的机制中,环形缓冲区就可以理解为数据码流的通道,每一个通道都对应着一个环形缓冲区,这样数据在读取和写入的时候都可以在这个缓冲区里循环进行,程序员可以根据自己需要的数据大小来决定自己使用的缓冲区大小。 环形缓冲区,顾名思义这个缓冲区是环形的,那么何谓环形这个意思也很好理解,就是用一个指针去访问该缓冲区的最后一个内存位置的的后一位置时回到环形缓冲区的起点。类似一个环一样。这样形容就很好理解了,当然有办法实现了。我在这里采用了2种方式实现了环形缓冲区,一个是用数组的方法,一个是用链表的方法。 数组是一块连续的内存,所以顺序访问时只要根据下标的增加而增加,但是最后一个元素之后需要回到起始位置,这就需要我们对这个地方进行特殊处理。只要最后一个地址访问结束能顺利回到起始地址,这个缓冲区就可以实现。代码如下: [cpp] view plaincopyprint? 01./* File name: ringbuf.c 02. * Author : wanxiao 03. * Function :Implement a circular buffer, 04. you can read and write data in the buffer zone. 05. */ 06. 07.#include <stdio.h> 08. 09.#define MAXSIZE 8 10. 11.int ringbuf[MAXSIZE]; 12.int readldx=0; 13.int writeldx=0; 14. 15.int next_data_handle(int addr) 16.{ 17. return (addr+1) == MAXSIZE ? 0:(addr+1) ; 18.} 19. 20.int write_data(int data) 21.{ 22. int i; 23. *(ringbuf+writeldx) = data; 24. writeldx = next_data_handle(writeldx); 25. for(i=0;i<MAXSIZE;i++) 26. { 27. printf("%4d",*(ringbuf+i)); 28. if(MAXSIZE-1 == i) 29. printf("/n"); 30. } 31.} 32. 33.int read_data() 34.{ 35. printf("read data is : %d/n",*(ringbuf+readldx)); 36. readldx = next_data_handle(readldx); 37.} 38. 39.int main(int argc , char **argv) 40.{ 41. int data; 42. char cmd; 43. 44. do{ 45. printf("select:/nw/t--write/nr/t--read/nq/t--quit/n"); 46. scanf("%s",&cmd); 47. 48. switch(cmd) 49. { 50. case 'w' : 51. printf("please input data:"); 52. scanf("%d",&data); 53. write_data(data); 54. break; 55. case 'r' : 56. data = read_data(); 57. break; 58. case 'q' : 59. printf("quit/n"); 60. break; 61. default : 62. printf("Command error/n"); 63. } 64. }while(cmd != 'q'); 65. return 0; 66.} /* File name: ringbuf.c * Author : wanxiao * Function :Implement a circular buffer, you can read and write data in the buffer zone. */ #include <stdio.h> #define MAXSIZE 8 int ringbuf[MAXSIZE]; int readldx=0; int writeldx=0; int next_data_handle(int addr) { return (addr+1) == MAXSIZE ? 0:(addr+1) ; } int write_data(int data) { int i; *(ringbuf+writeldx) = data; writeldx = next_data_handle(writeldx); for(i=0;i<MAXSIZE;i++) { printf("%4d",*(ringbuf+i)); if(MAXSIZE-1 == i) printf("/n"); } } int read_data() { printf("read data is : %d/n",*(ringbuf+readldx)); readldx = next_data_handle(readldx); } int main(int argc , char **argv) { int data; char cmd; do{ printf("select:/nw/t--write/nr/t--read/nq/t--quit/n"); scanf("%s",&cmd); switch(cmd) { case 'w' : printf("please input data:"); scanf("%d",&data); write_data(data); break; case 'r' : data = read_data(); break; case 'q' : printf("quit/n"); break; default : printf("Command error/n"); } }while(cmd != 'q'); return 0; } 链表实现,实际上就是一个单向循环链表。这个方法的优点是不需要最后一个元素进行特殊处理,但是实现起来比数组稍微麻烦一点,单思路还是很清晰简单的。代码如下: [cpp] view plaincopyprint? 01.#include <stdio.h> 02.#include <stdlib.h> 03. 04. 05.typedef struct signal_loop_chain 06.{ 07. int data; 08. struct signal_loop_chain *next; 09.}NODE; 10. 11.NODE *Create_loop_chain(int n) 12.{ 13. int i; 14. NODE *head , *previous , *current ; 15. previous = (NODE *)malloc(sizeof(NODE)); 16. if(previous == NULL) 17. exit(1); 18. 19. previous->data =0; 20. previous->next = NULL; 21. head = previous ; 22. 23. for(i=0 ; i<n ; i++) 24. { 25. current = (NODE*)malloc(sizeof(NODE)); 26. if(current == NULL) 27. exit(1); 28. 29.// scanf("%d",¤t->data); 30. current->next = head; 31. previous->next = current; 32. previous = current ; 33. } 34. return head ; 35.} 36. 37.int Show(NODE *head) 38.{ 39. NODE *current; 40. current = head->next ; 41. printf("List:/n"); 42. while(current != head) 43. { 44. printf("%4d",current->data); 45. current = current->next; 46. } 47. printf("/n"); 48.} 49. 50.int read_buf(NODE *head) 51.{ 52. NODE *current; 53. current = head->next; 54. while(1) 55. { 56. printf("read number is %d/n",current->data); 57. current = current->next; 58. sleep(1); 59. } 60. 61.} 62. 63.int write_buf(NODE *head) 64.{ 65. NODE *current; 66. int i = 0; 67. current = head->next; 68. while(1) 69. { 70. current->data = i++; 71. printf("write number is %d/n",current->data); 72. current = current->next; 73. sleep(1); 74. } 75.} 76. 77.int main(int argc , char **argv) 78.{ 79. int num; 80. char cmd; 81. NODE *head; 82. printf("please input node_num /n"); 83. scanf("%d",&num); 84. head = Create_loop_chain(num); 85. printf("The ringbuf was found/n"); 86. Show(head); 87. 88. while(1){ 89. printf("please select r or w/n"); 90. scanf("%c",&cmd); 91. 92. if(cmd == 'r'){ 93. read_buf(head); 94. Show(head); 95. } 96. 97. if(cmd == 'w'){ 98. write_buf(head); 99. Show(head); 100. } 101. 102. } 103. return 0; 104.} #include <stdio.h> #include <stdlib.h> typedef struct signal_loop_chain { int data; struct signal_loop_chain *next; }NODE; NODE *Create_loop_chain(int n) { int i; NODE *head , *previous , *current ; previous = (NODE *)malloc(sizeof(NODE)); if(previous == NULL) exit(1); previous->data =0; previous->next = NULL; head = previous ; for(i=0 ; i<n ; i++) { current = (NODE*)malloc(sizeof(NODE)); if(current == NULL) exit(1); // scanf("%d",¤t->data); current->next = head; previous->next = current; previous = current ; } return head ; } int Show(NODE *head) { NODE *current; current = head->next ; printf("List:/n"); while(current != head) { printf("%4d",current->data); current = current->next; } printf("/n"); } int read_buf(NODE *head) { NODE *current; current = head->next; while(1) { printf("read number is %d/n",current->data); current = current->next; sleep(1); } } int write_buf(NODE *head) { NODE *current; int i = 0; current = head->next; while(1) { current->data = i++; printf("write number is %d/n",current->data); current = current->next; sleep(1); } } int main(int argc , char **argv) { int num; char cmd; NODE *head; printf("please input node_num /n"); scanf("%d",&num); head = Create_loop_chain(num); printf("The ringbuf was found/n"); Show(head); while(1){ printf("please select r or w/n"); scanf("%c",&cmd); if(cmd == 'r'){ read_buf(head); Show(head); } if(cmd == 'w'){ write_buf(head); Show(head); } } return 0; } 以上都是针对单进程而言。对于系统,尤其是嵌入式Linux系统中,缓冲区的保护机制就变得尤为重要了,因为我们的数据时不停的在读写,内存不停的变化,如果牵扯到多任务(多进程,多线程),我们就需要加锁对其进行保护措施。这里我在链表的实现下加了信号量加以保护。 [c-sharp] view plaincopyprint? 01.#include <stdio.h> 02.#include <stdlib.h> 03.#include <pthread.h> 04.#include <semaphore.h> 05. 06.sem_t mutex; 07. 08.typedef struct signal_loop_chain 09.{ 10. int data; 11. struct signal_loop_chain *next; 12.}NODE; 13. 14.NODE *Create_loop_chain(int n) 15.{ 16. int i; 17. NODE *head , *previous , *current ; 18. previous = (NODE *)malloc(sizeof(NODE)); 19. if(previous == NULL) 20. exit(1); 21. 22. previous->data =0; 23. previous->next = NULL; 24. head = previous ; 25. 26. for(i=0 ; i<n ; i++) 27. { 28. current = (NODE*)malloc(sizeof(NODE)); 29. if(current == NULL) 30. exit(1); 31. 32. current->next = head; 33. previous->next = current; 34. previous = current ; 35. } 36. return head ; 37.} 38. 39.int Show(NODE *head) 40.{ 41. NODE *current; 42. current = head->next ; 43. printf("List:/n"); 44. while(current != head) 45. { 46. printf("%4d",current->data); 47. current = current->next; 48. } 49. printf("/n"); 50.} 51. 52.int read_buf(NODE *head) 53.{ 54. NODE *current; 55. current = head->next; 56. while(1) 57. { 58. sem_wait(&mutex); 59. printf("read number is %d/n",current->data); 60. current = current->next; 61. sem_post(&mutex); 62. sleep(2); 63. } 64. 65.} 66. 67.int write_buf(NODE *head) 68.{ 69. NODE *current; 70. int i = 0; 71. current = head->next; 72. while(1) 73. { 74. sem_wait(&mutex); 75. current->data = i++; 76. printf("write number is %d/n",current->data); 77. current = current->next; 78. sem_post(&mutex); 79. sleep(1); 80. } 81.} 82. 83.int main(int argc , char **argv) 84.{ 85. int num,ret; 86. char cmd; 87. NODE *head; 88. pthread_t id1,id2; 89. 90. ret = sem_init(&mutex ,0,1); 91. if(ret != 0){ 92. perror("sem_init error"); 93. } 94. printf("please input node_num /n"); 95. scanf("%d",&num); 96. head = Create_loop_chain(num); 97. printf("The ringbuf was found/n"); 98. Show(head); 99. 100. ret = pthread_create(&id1,NULL,(void *)write_buf,head); 101. ret = pthread_create(&id2,NULL,(void *)read_buf,head); 102. 103. pthread_join(id1,NULL); 104. pthread_join(id2,NULL); 105. 106. 107. return 0; 108.}
相关文章推荐
- Activity界面显示全解析
- 程序员创业的福音,加速创业,写在XE10 Seattle Update1发布后
- C++指针与引用
- Android平台的崩溃捕获机制及实现
- HTML5前端(移动端网站)性能优化指南
- C# WebBrowser控件 模拟登录 抓取数据
- <安卓那点事>写一个简单的电话拨号器
- FLV容器分析2
- Android 实现图片高斯模糊算法,真正有效的工具类
- HBase拆分策略
- 原子性、唯一性的软件架构问题
- 微信红包接口---你不知道的坑爹官方支付文档
- RecyclerView的使用方法和瀑布流的实现
- 使用FLASHBACK TABLE 恢复被删除表
- nova修改libvirt.xml及自定义xml文件修改nova代码支持vhost
- 自动化测试工具QTP(破解)10.0版本
- 在php中设置session用memcache来存储的方法总结
- mysql where 条件中的字段有NULL值时的sql语句写法
- Java日期时间使用总结
- Composer安装出错——Unable to connect to getcomposer.org