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

  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.}    
上一篇:工业物联网或系统集成中应用消息队列(ActiveMQ,C#的demo)的场景全面分析


下一篇:机器视觉基础知识详解