링 버퍼란?
고정된 크기의 큐의 양 끝을 이어 원형 모양처럼 사용하는 버퍼
데이터를 넣었다가 빼는 역할을 할 수 있다
구현은 다음과 같이 하였다.
ring_buffer.h
#include <stdint.h>
#include <string.h>
typedef struct{
uint8_t *buffer;
int front;
int rear;
int maxlen;
}ring_buffer_t;
void ring_buf_init(ring_buffer_t *rbuf, uint8_t *buffer, int size);
uint8_t ring_buf_push(ring_buffer_t *rbuf, uint8_t data);
uint8_t ring_buf_pop(ring_buffer_t *rubf, uint8_t *data);
uint8_t ring_buf_is_full(ring_buffer_t *rbuf);
uint8_t ring_buf_is_empty(ring_buffer_t *rbuf);
void ring_buf_clear(ring_buffer_t *rbuf);
ring_buffer_t는
사용할 버퍼를 담을 uint_t *buffer 와 큐를 사용하기 위한 fornt, rear와 사용할 버퍼의 크기를 maxlen으로 한다.
ring_buffer.c
#include <stdint.h>
#include <string.h>
void ring_buf_init(ring_buffer_t *rbuf, uint8_t *buffer, int size){
memset(rbuf, 0x00, sizeof(ring_buffer_t));
rbuf->buffer=buffer;
rbuf->maxlen=size;
}
uint8_t ring_buf_is_full(ring_buffer_t *rbuf){
if(rbuf->rear == ( rbuf->front+1 ) % rbuf->maxlen) return 1;
else return 0;
}
uint8_t ring_buf_is_empty(ring_buffer_t *rbuf){
if( rbuf->rear == rbuf->front) return 1;
else return 0;
}
uint8_t ring_buf_push(ring_buffer_t *rbuf, uint8_t data){
if( ring_buf_is_full(rbuf) ) return 0;
rbuf->buffer[rbuf->front] = data;
rbuf->front = ( rbuf->front + 1) % rbuf->maxlen;
return 1;
}
uint8_t ring_buf_pop(ring_buffer_t *rbuf, uint8_t *data){
if( ring_buf_is_empty(rbuf) ) return 0;
*data=rbuf->buffer[rbuf->rear];
rbuf->rear = (rbuf->rear + 1) % rbuf->maxlen;
return 1;
}
void ring_buf_clear(ring_buffer_t *rbuf){
rbuf->front=0;
rbuf->rear=0;
}
사용 예시
#include <stdio.h>
#include <stdint.h>
#include "ring_buffer.h"
int main(){
uint8_t i=0;
uint8_t pop_data=0;
ring_buffer_t ring_buffer;
uint8_t rbuf[3];
ring_buf_init(&ring_buffer, rbuf, 3);
for(i=0;i<5;i++){
if (ring_buf_push(&ring_buffer, i)){
printf("push data : %d\r\n",i );
}
}
for(i=0;i<5;i++){
if (ring_buf_pop(&ring_buffer,&pop_data)){
printf("pop %d \r\n", pop_data);
}
}
return 0;
}
1. ring_buf_init(&ring_buffer, rbuf, 3);
-> ring_buffer 구조체에 rbuf로 초기화 한다.
2. 0~5를 ring buffer에 순차적으로 push 한다.
3. ring_buffer의 데이터를 pop_data에 5번 pop한다.
결과
rbuf의 크기는 3인데 데이터는 2개를 넣은 후, 3개째에서 링 버퍼가 가득 찼다고 나온다.
이는 링 버퍼의 경우, empty와 full을 구분하기 위해 full의 경우 한 칸을 비워두기 때문이다.
나는 3개를 만들었으면 3개를 다 쓰고 싶다고 한다면 ring_buffer.h에서 ring_buffer_init 할 때 maxlen을 버퍼의 크기보다 1개 더 크게 해주면 된다.
void ring_buf_init(ring_buffer_t* rbuf, uint8_t* buffer, uint16_t size){
memset(rbuf,0x00,sizeof(ring_buffer_t));
rbuf->buffer = buffer;
rbuf->maxlen = size+1;
}
이렇게 고치고 똑같이 테스트를 하면
버퍼의 크기만큼 모두 이용할 수 있다.
물론 테스트를 많이 안해봐서 오류가 있을 수도.....
끝
반응형
'지식저장소 > C' 카테고리의 다른 글
[C] Moving Average Filter (이동 평균 필터) (0) | 2022.04.28 |
---|---|
[C] AverageFilter (평균 필터) (0) | 2022.04.28 |
[C/BOJ] 9012 괄호 - Stack이용 (0) | 2022.02.16 |
[C]구조체를 이용한 Stack 구현 (0) | 2022.02.16 |
[C/STM32] Uart로 printf 대신하기 (0) | 2022.01.14 |