嵌入式 环形缓冲区的设计与实现

  1. 环形缓冲区是嵌入式系统中十分重要的一种数据结构,比如在一个视频处理的机制中,环形缓冲区就可以理解为数据码流的通道,每一个通道都对应着一个环形缓冲区,这样数据在读取和写入的时候都可以在这个缓冲区里循环进行,程序员可以根据自己需要的数据大小来决定自己使用的缓冲区大小。  
  2.   
  3.     环形缓冲区,顾名思义这个缓冲区是环形的,那么何谓环形这个意思也很好理解,就是用一个指针去访问该缓冲区的最后一个内存位置的的后一位置时回到环形缓冲区的起点。类似一个环一样。这样形容就很好理解了,当然有办法实现了。我在这里采用了2种方式实现了环形缓冲区,一个是用数组的方法,一个是用链表的方法。  
  4.   
  5.     数组是一块连续的内存,所以顺序访问时只要根据下标的增加而增加,但是最后一个元素之后需要回到起始位置,这就需要我们对这个地方进行特殊处理。只要最后一个地址访问结束能顺利回到起始地址,这个缓冲区就可以实现。代码如下:  
  6.   
  7. [cpp] view plaincopyprint?  
  8. 01./* File name: ringbuf.c   
  9. 02. * Author   : wanxiao   
  10. 03. * Function :Implement a circular buffer,    
  11. 04.             you can read and write data in the buffer zone.   
  12. 05. */    
  13. 06.    
  14. 07.#include <stdio.h>        
  15. 08.      
  16. 09.#define MAXSIZE 8        
  17. 10.      
  18. 11.int ringbuf[MAXSIZE];       
  19. 12.int readldx=0;    
  20. 13.int writeldx=0;    
  21. 14.    
  22. 15.int next_data_handle(int addr)       
  23. 16.{       
  24. 17.    return (addr+1) == MAXSIZE ? 0:(addr+1) ;       
  25. 18.}       
  26. 19.      
  27. 20.int write_data(int data)    
  28. 21.{    
  29. 22.    int i;    
  30. 23.    *(ringbuf+writeldx) = data;    
  31. 24.    writeldx = next_data_handle(writeldx);    
  32. 25.    for(i=0;i<MAXSIZE;i++)    
  33. 26.    {    
  34. 27.        printf("%4d",*(ringbuf+i));    
  35. 28.        if(MAXSIZE-1 == i)    
  36. 29.            printf("/n");    
  37. 30.    }    
  38. 31.}    
  39. 32.    
  40. 33.int read_data()    
  41. 34.{    
  42. 35.    printf("read data is : %d/n",*(ringbuf+readldx));    
  43. 36.    readldx = next_data_handle(readldx);    
  44. 37.}    
  45. 38.      
  46. 39.int main(int argc , char **argv)       
  47. 40.{       
  48. 41.    int data;       
  49. 42.    char cmd;    
  50. 43.    
  51. 44.    do{       
  52. 45.        printf("select:/nw/t--write/nr/t--read/nq/t--quit/n");       
  53. 46.        scanf("%s",&cmd);       
  54. 47.      
  55. 48.        switch(cmd)       
  56. 49.        {       
  57. 50.            case 'w' :       
  58. 51.                printf("please input data:");       
  59. 52.                scanf("%d",&data);       
  60. 53.                write_data(data);       
  61. 54.                break;       
  62. 55.            case 'r' :       
  63. 56.                data = read_data();       
  64. 57.                break;       
  65. 58.            case 'q' :       
  66. 59.                printf("quit/n");       
  67. 60.                break;       
  68. 61.            default :       
  69. 62.                printf("Command  error/n");       
  70. 63.        }       
  71. 64.    }while(cmd != 'q');       
  72. 65.    return 0;       
  73. 66.}    
  74. /* File name: ringbuf.c  
  75.  * Author   : wanxiao  
  76.  * Function :Implement a circular buffer,   
  77.              you can read and write data in the buffer zone.  
  78.  */  
  79.   
  80. #include <stdio.h>     
  81.     
  82. #define MAXSIZE 8     
  83.     
  84. int ringbuf[MAXSIZE];     
  85. int readldx=0;  
  86. int writeldx=0;  
  87.   
  88. int next_data_handle(int addr)     
  89. {     
  90.     return (addr+1) == MAXSIZE ? 0:(addr+1) ;     
  91. }     
  92.     
  93. int write_data(int data)  
  94. {  
  95.     int i;  
  96.     *(ringbuf+writeldx) = data;  
  97.     writeldx = next_data_handle(writeldx);  
  98.     for(i=0;i<MAXSIZE;i++)  
  99.     {  
  100.         printf("%4d",*(ringbuf+i));  
  101.         if(MAXSIZE-1 == i)  
  102.             printf("/n");  
  103.     }  
  104. }  
  105.   
  106. int read_data()  
  107. {  
  108.     printf("read data is : %d/n",*(ringbuf+readldx));  
  109.     readldx = next_data_handle(readldx);  
  110. }  
  111.     
  112. int main(int argc , char **argv)     
  113. {     
  114.     int data;     
  115.     char cmd;  
  116.   
  117.     do{     
  118.         printf("select:/nw/t--write/nr/t--read/nq/t--quit/n");     
  119.         scanf("%s",&cmd);     
  120.     
  121.         switch(cmd)     
  122.         {     
  123.             case 'w' :     
  124.                 printf("please input data:");     
  125.                 scanf("%d",&data);     
  126.                 write_data(data);     
  127.                 break;     
  128.             case 'r' :     
  129.                 data = read_data();     
  130.                 break;     
  131.             case 'q' :     
  132.                 printf("quit/n");     
  133.                 break;     
  134.             default :     
  135.                 printf("Command  error/n");     
  136.         }     
  137.     }while(cmd != 'q');     
  138.     return 0;     
  139. }  
  140.    
  141.   
  142.    
  143.   
  144.     链表实现,实际上就是一个单向循环链表。这个方法的优点是不需要最后一个元素进行特殊处理,但是实现起来比数组稍微麻烦一点,单思路还是很清晰简单的。代码如下:  
  145.   
  146. [cpp] view plaincopyprint?  
  147. 01.#include <stdio.h>     
  148. 02.#include <stdlib.h>     
  149. 03.    
  150. 04.    
  151. 05.typedef struct signal_loop_chain    
  152. 06.{    
  153. 07.    int data;    
  154. 08.    struct signal_loop_chain *next;    
  155. 09.}NODE;    
  156. 10.    
  157. 11.NODE *Create_loop_chain(int n)    
  158. 12.{    
  159. 13.    int i;    
  160. 14.    NODE *head , *previous , *current ;    
  161. 15.    previous = (NODE *)malloc(sizeof(NODE));    
  162. 16.    if(previous == NULL)    
  163. 17.        exit(1);    
  164. 18.    
  165. 19.    previous->data =0;    
  166. 20.    previous->next = NULL;    
  167. 21.    head = previous ;    
  168. 22.    
  169. 23.    for(i=0 ; i<n ; i++)    
  170. 24.    {    
  171. 25.        current = (NODE*)malloc(sizeof(NODE));    
  172. 26.        if(current == NULL)    
  173. 27.            exit(1);    
  174. 28.    
  175. 29.//      scanf("%d",¤t->data);     
  176. 30.        current->next = head;    
  177. 31.        previous->next = current;    
  178. 32.        previous = current ;    
  179. 33.    }    
  180. 34.    return head ;    
  181. 35.}    
  182. 36.    
  183. 37.int Show(NODE *head)    
  184. 38.{    
  185. 39.    NODE *current;    
  186. 40.    current = head->next ;    
  187. 41.    printf("List:/n");    
  188. 42.    while(current != head)    
  189. 43.    {    
  190. 44.        printf("%4d",current->data);    
  191. 45.        current = current->next;    
  192. 46.    }    
  193. 47.    printf("/n");    
  194. 48.}    
  195. 49.    
  196. 50.int read_buf(NODE *head)    
  197. 51.{    
  198. 52.    NODE *current;    
  199. 53.    current = head->next;    
  200. 54.    while(1)    
  201. 55.    {    
  202. 56.        printf("read number is %d/n",current->data);    
  203. 57.        current = current->next;    
  204. 58.        sleep(1);    
  205. 59.    }    
  206. 60.    
  207. 61.}    
  208. 62.    
  209. 63.int write_buf(NODE *head)    
  210. 64.{    
  211. 65.    NODE *current;    
  212. 66.    int i = 0;    
  213. 67.    current = head->next;    
  214. 68.    while(1)    
  215. 69.    {    
  216. 70.        current->data = i++;    
  217. 71.        printf("write number is %d/n",current->data);    
  218. 72.        current = current->next;    
  219. 73.        sleep(1);    
  220. 74.    }    
  221. 75.}    
  222. 76.    
  223. 77.int main(int argc , char **argv)    
  224. 78.{    
  225. 79.    int num;    
  226. 80.    char cmd;    
  227. 81.    NODE *head;    
  228. 82.    printf("please input node_num /n");    
  229. 83.    scanf("%d",&num);    
  230. 84.    head = Create_loop_chain(num);    
  231. 85.    printf("The ringbuf was found/n");    
  232. 86.    Show(head);    
  233. 87.    
  234. 88.    while(1){    
  235. 89.        printf("please select r or w/n");    
  236. 90.        scanf("%c",&cmd);    
  237. 91.    
  238. 92.        if(cmd == 'r'){    
  239. 93.            read_buf(head);    
  240. 94.            Show(head);    
  241. 95.        }    
  242. 96.            
  243. 97.        if(cmd == 'w'){    
  244. 98.            write_buf(head);    
  245. 99.            Show(head);    
  246. 100.        }    
  247. 101.            
  248. 102.    }    
  249. 103.    return 0;    
  250. 104.}    
  251. #include <stdio.h>  
  252. #include <stdlib.h>  
  253.   
  254.   
  255. typedef struct signal_loop_chain  
  256. {  
  257.     int data;  
  258.     struct signal_loop_chain *next;  
  259. }NODE;  
  260.   
  261. NODE *Create_loop_chain(int n)  
  262. {  
  263.     int i;  
  264.     NODE *head , *previous , *current ;  
  265.     previous = (NODE *)malloc(sizeof(NODE));  
  266.     if(previous == NULL)  
  267.         exit(1);  
  268.   
  269.     previous->data =0;  
  270.     previous->next = NULL;  
  271.     head = previous ;  
  272.   
  273.     for(i=0 ; i<n ; i++)  
  274.     {  
  275.         current = (NODE*)malloc(sizeof(NODE));  
  276.         if(current == NULL)  
  277.             exit(1);  
  278.   
  279. //      scanf("%d",¤t->data);  
  280.         current->next = head;  
  281.         previous->next = current;  
  282.         previous = current ;  
  283.     }  
  284.     return head ;  
  285. }  
  286.   
  287. int Show(NODE *head)  
  288. {  
  289.     NODE *current;  
  290.     current = head->next ;  
  291.     printf("List:/n");  
  292.     while(current != head)  
  293.     {  
  294.         printf("%4d",current->data);  
  295.         current = current->next;  
  296.     }  
  297.     printf("/n");  
  298. }  
  299.   
  300. int read_buf(NODE *head)  
  301. {  
  302.     NODE *current;  
  303.     current = head->next;  
  304.     while(1)  
  305.     {  
  306.         printf("read number is %d/n",current->data);  
  307.         current = current->next;  
  308.         sleep(1);  
  309.     }  
  310.   
  311. }  
  312.   
  313. int write_buf(NODE *head)  
  314. {  
  315.     NODE *current;  
  316.     int i = 0;  
  317.     current = head->next;  
  318.     while(1)  
  319.     {  
  320.         current->data = i++;  
  321.         printf("write number is %d/n",current->data);  
  322.         current = current->next;  
  323.         sleep(1);  
  324.     }  
  325. }  
  326.   
  327. int main(int argc , char **argv)  
  328. {  
  329.     int num;  
  330.     char cmd;  
  331.     NODE *head;  
  332.     printf("please input node_num /n");  
  333.     scanf("%d",&num);  
  334.     head = Create_loop_chain(num);  
  335.     printf("The ringbuf was found/n");  
  336.     Show(head);  
  337.   
  338.     while(1){  
  339.         printf("please select r or w/n");  
  340.         scanf("%c",&cmd);  
  341.   
  342.         if(cmd == 'r'){  
  343.             read_buf(head);  
  344.             Show(head);  
  345.         }  
  346.           
  347.         if(cmd == 'w'){  
  348.             write_buf(head);  
  349.             Show(head);  
  350.         }  
  351.           
  352.     }  
  353.     return 0;  
  354. }  
  355.    
  356.   
  357.    
  358.   
  359.    
  360.   
  361.    
  362.   
  363.     以上都是针对单进程而言。对于系统,尤其是嵌入式Linux系统中,缓冲区的保护机制就变得尤为重要了,因为我们的数据时不停的在读写,内存不停的变化,如果牵扯到多任务(多进程,多线程),我们就需要加锁对其进行保护措施。这里我在链表的实现下加了信号量加以保护。  
  364.   
  365. [c-sharp] view plaincopyprint?  
  366. 01.#include <stdio.h>    
  367. 02.#include <stdlib.h>    
  368. 03.#include <pthread.h>    
  369. 04.#include <semaphore.h>     
  370. 05.    
  371. 06.sem_t mutex;    
  372. 07.    
  373. 08.typedef struct signal_loop_chain    
  374. 09.{    
  375. 10.    int data;    
  376. 11.    struct signal_loop_chain *next;    
  377. 12.}NODE;    
  378. 13.    
  379. 14.NODE *Create_loop_chain(int n)    
  380. 15.{    
  381. 16.    int i;    
  382. 17.    NODE *head , *previous , *current ;    
  383. 18.    previous = (NODE *)malloc(sizeof(NODE));    
  384. 19.    if(previous == NULL)    
  385. 20.        exit(1);    
  386. 21.    
  387. 22.    previous->data =0;    
  388. 23.    previous->next = NULL;    
  389. 24.    head = previous ;    
  390. 25.    
  391. 26.    for(i=0 ; i<n ; i++)    
  392. 27.    {    
  393. 28.        current = (NODE*)malloc(sizeof(NODE));    
  394. 29.        if(current == NULL)    
  395. 30.            exit(1);    
  396. 31.    
  397. 32.        current->next = head;    
  398. 33.        previous->next = current;    
  399. 34.        previous = current ;    
  400. 35.    }    
  401. 36.    return head ;    
  402. 37.}    
  403. 38.    
  404. 39.int Show(NODE *head)    
  405. 40.{    
  406. 41.    NODE *current;    
  407. 42.    current = head->next ;    
  408. 43.    printf("List:/n");    
  409. 44.    while(current != head)    
  410. 45.    {    
  411. 46.        printf("%4d",current->data);    
  412. 47.        current = current->next;    
  413. 48.    }    
  414. 49.    printf("/n");    
  415. 50.}    
  416. 51.    
  417. 52.int read_buf(NODE *head)    
  418. 53.{    
  419. 54.    NODE *current;    
  420. 55.    current = head->next;    
  421. 56.    while(1)    
  422. 57.    {    
  423. 58.        sem_wait(&mutex);    
  424. 59.        printf("read number is %d/n",current->data);    
  425. 60.        current = current->next;    
  426. 61.        sem_post(&mutex);    
  427. 62.        sleep(2);    
  428. 63.    }    
  429. 64.    
  430. 65.}    
  431. 66.    
  432. 67.int write_buf(NODE *head)    
  433. 68.{    
  434. 69.    NODE *current;    
  435. 70.    int i = 0;    
  436. 71.    current = head->next;    
  437. 72.    while(1)    
  438. 73.    {    
  439. 74.        sem_wait(&mutex);    
  440. 75.        current->data = i++;    
  441. 76.        printf("write number is %d/n",current->data);    
  442. 77.        current = current->next;    
  443. 78.        sem_post(&mutex);    
  444. 79.        sleep(1);    
  445. 80.    }    
  446. 81.}    
  447. 82.    
  448. 83.int main(int argc , char **argv)    
  449. 84.{    
  450. 85.    int num,ret;    
  451. 86.    char cmd;    
  452. 87.    NODE *head;    
  453. 88.    pthread_t id1,id2;    
  454. 89.    
  455. 90.    ret = sem_init(&mutex ,0,1);    
  456. 91.    if(ret != 0){    
  457. 92.        perror("sem_init error");    
  458. 93.    }    
  459. 94.    printf("please input node_num /n");    
  460. 95.    scanf("%d",&num);    
  461. 96.    head = Create_loop_chain(num);    
  462. 97.    printf("The ringbuf was found/n");    
  463. 98.    Show(head);    
  464. 99.    
  465. 100.    ret = pthread_create(&id1,NULL,(void *)write_buf,head);    
  466. 101.    ret = pthread_create(&id2,NULL,(void *)read_buf,head);    
  467. 102.    
  468. 103.    pthread_join(id1,NULL);    
  469. 104.    pthread_join(id2,NULL);    
  470. 105.        
  471. 106.    
  472. 107.    return 0;    
  473. 108.}    
时间: 2024-10-02 08:02:06

嵌入式 环形缓冲区的设计与实现的相关文章

C#环形缓冲区(队列)完全实现_C#教程

公司项目中经常设计到串口通信,TCP通信,而且大多都是实时的大数据的传输,然后大家都知道协议通讯肯定涉及到什么,封包.拆包.粘包.校验--什么鬼的概念一大堆,说简单点儿就是要一个高效率可复用的缓存区.按照码农的惯性思维就是去百度.谷歌搜索看有没有现成的东西可以直接拿来用,然而我并没有找到,好吧不是很难的东西自己实现一个呗.开扯--  为什么要用环形队列?环形队列是在实际编程极为有用的数据结构,它有如下特点: 它是一个首尾相连的FIFO的数据结构,采用数组的线性空间,数据组织简单.能很快知道队列是

服务器公共组件实现 -- 环形缓冲区

消息队列锁调用太频繁的问题算是解决了,另一个让人有些苦恼的大概是这太多的内存分配和释放操作了.频繁的内存分配不但增加了系统开销,更使得内存碎片不断增多,非常不利于我们的服务器长期稳定运行.也许我们可以使用内存池,比如SGI STL中附带的小内存分配器.但是对于这种按照严格的先进先出顺序处理的,块大小并不算小的,而且块大小也并不统一的内存分配情况来说,更多使用的是一种叫做环形缓冲区的方案,mangos的网络代码中也有这么一个东西,其原理也是比较简单的. 就好比两个人围着一张圆形的桌子在追逐,跑的人

线程安全的环形缓冲区实现

来源:http://blog.csdn.net/lezhiyong    应用背景:线程1将每次数量不一的音频采样点(PCM音频数据)写入环形缓冲区,线程2每次取固定数量采样点送音频编码器,线程1线程2在平均时间内的读写数据量相等.(倒入桶中的水量有时大有时小,但每次取一瓢喝:)   该环形缓冲区借鉴CoolPlayer音频播放器中的环形缓冲区代码实现,在读写操作函数中加了锁,允许多线程同时操作.CPs_CircleBuffer基于内存段的读写,比用模板实现的环形缓冲队列适用的数据类型更广些,

C 语言中实现环形缓冲区_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

Windows CE嵌入式导航系统研究(硬件设计1)

1.1 ARM微处理器的选择 1.1.1 ARM微处理器系列 ARM 微处理器目前包括下面几个系列,其它厂商基于ARM 架构的处理器,除了具有ARM 架构的共同特点以外,每一个系列的ARM 微处理器都有各自的特点和应用领域. l ARM7 系列 l ARM9 系列 l ARM9E 系列 l ARM10E 系列 l SecurCore 系列 l Inter 的Xscale l Inter 的StrongARM 其中,ARM7.ARM9.ARM9E 和ARM10E 为4 个通用处理器系列,每一个系列

Windows CE嵌入式导航系统研究(硬件设计2)

1.1 嵌入式处理器 S3C2440A[17] S3C2440A是一款专用的以手持设备为主而设计的芯片,其特点有低功耗,高速的处理计算能力.为了减少系统的耗费,2440使用了如下组件:2440基于ARM920T内核的,0.13Um cmos 标准单元和存储单元复合体,它功耗及小.简单.稳定的设计非常适合对电源要求较高的产品上.S3C2440A采用ARM920T内核,如图 4.1所示ARM920T的结构图. 图 4.1 ARM920T 的结构框图 S3C2440A片上集成了如下功能: l 1.2V

Windows CE嵌入式导航系统研究(硬件设计3)

1.1 Flash接口电路设计 Flash 存储器是一种在系统上(In-System)进行电擦写,掉电后信息不丢失的存储器.它具有低功耗.大容量.擦写速度快.可整片或分扇区在系统编程.擦除等特点.并且由内部嵌入式的算法完成对芯片的操作,因而在各种嵌入式系统中得到了广泛的应用.现在市场上两种主要的非易失闪存技术是 NOR 和NAND.NOR 的特点是芯片内执行,这样应用程序可以直接在 Flash 内运行,不必再把代码读到系统 RAM 中.NOR 的传输效率很高,在 1~4MB 的小容量时具有很高的

《 嵌入式系统设计与实践》一一3.7 处理错误

3.7 处理错误 代码的生命周期让我震惊.因为有时侯好像我们总在以不同的方式重写同样的旧代码,有一天我们可能会发现自己在10年前入门阶段写的一段代码正在被一个财富500强公司使用.既然代码工作的如此之好,为什么还要修复其中那些隐藏很深的问题呢? 在某些时候,代码将失效.这一点可能让人会感到可怕.一个错误的发生,要么是由于代码本身,要么是由于环境中一个意想不到的情况.有两种方法来处理错误.首先,该系统可以进入优雅降级的状态,在这个状态中软件会尽可能做到最好.或者,系统可能会优雅地立即失效.长期运行

ARM嵌入式系统的问题分析与总结

引言     由于各种新型微处理器的出现和应用的不断深化,嵌入式系统在后PC时代得到了空前的发展.随着时间的推移和技术的进步,在工业控制和新兴的手持式应用等领域,用户体验成为产品成功的关键因素之一,越来越多的产品需要良好的用户界面.互联功能以及较强的数据处理能力,这对嵌入式处理器硬件.软件.教学等提出了新的要求.     1  嵌入式处理器与硬件     在处理器方面,目前大量的中.低端嵌入式应用,主要使用8/16位单片机.在国内,由于历史的原因,主要是以MCS51核为主的许多不同型号单片机,主