在不同的系统之间交换数据时,往往由于两个系统时间不能完全同步。
为了保证生产者和消费者的同步,需要使用环形缓冲区。生产者以某一速度存入数据,消费者以某一速度取出数据,两者的速度不用时刻一致,但总体的平均速度必须相等!
以下是具体实现:
/**************FIFO Begin**************************************************/
/*溢出标志:0-正常,-1-溢出*/
#define FLAGS_OVERRUN 0x0001
/*
buf- 缓冲区地址
size- 大小
free- 空余容量
putP- 下一个数据写入位置
getP- 下一个数据独处位置
*/
struct FIFO8{
char *buf;
int putP,getP,size,free,flags;
pthread_mutex_t mutex;
};
int fifo8_init(struct FIFO8 *fifo,int size);
int fifo8_put(struct FIFO8 *fifo, char data); //not mutiply thread safe
int fifo8_get(struct FIFO8 *fifo); //not mutiply thread safe
void fifo8_status(struct FIFO8 *fifo,int *len);
void fifo8_free(struct FIFO8 *fifo,int *len);
int fifo8_write(struct FIFO8 *fifo,char *data,int len);
int fifo8_read(struct FIFO8 *fifo,char *data,int len);
/*初始化*/
int fifo8_init(struct FIFO8 *fifo,int size) {
int ret=0;
fifo->flags=0;
fifo->free=size;
fifo->size=size;
fifo->putP=0;
fifo->getP=0;
fifo->buf=(char *)malloc(size);
if(fifo->buf==NULL){
LOGI("malloc fifo buffer failed!\n");
return -1;
}
ret = pthread_mutex_init(&(fifo->mutex),NULL);
if(ret <0){
LOGI("init mutex failed!\n");
return -1;
}
return 0;
}
/*向FIFO 中写入1个数据 */
int fifo8_putPut(struct FIFO8 *fifo, char data) {
if(fifo->free==0){
fifo->flags |= FLAGS_OVERRUN;
return -1;
}
fifo->buf[fifo->putP] = data;
fifo->putP++;
//循环队列缓冲区
if(fifo->putP == fifo->size){
fifo->putP = 0;
}
fifo->free--;
return 0;
}
/*从FIFO 中取出一个数据 */
int fifo8_get(struct FIFO8 *fifo) {
int data;
if(fifo->free == fifo->size){
return -1;
}
data = fifo->buf[fifo->getP++];
//fifo->getP++;
if(fifo->getP == fifo->size){//用来实现循环
fifo->getP = 0;
}
fifo->free++;
return data;
}
/*写入len个字节,返回写入的字节数*/
int fifo8_write(struct FIFO8 *fifo,char *data,int len){
int i=0;
pthread_mutex_lock(&(fifo->mutex));
if(fifo->free < len) {
pthread_mutex_unlock(&(fifo->mutex));
LOGI("the free size in not enough!\n");
return 0;
}
else {
LOGI("current fifo->putP =%d \n",fifo->putP);
for(i=0;i<len;i++){
fifo->buf[fifo->putP++] = *(data+i);
//循环队列缓冲区
if(fifo->putP == fifo->size){
fifo->putP = 0;
}
fifo->free--;
}
}
pthread_mutex_unlock(&(fifo->mutex));
return len;
}
/*读出len个字节,返回读出的字节数*/
int fifo8_read(struct FIFO8 *fifo,char *data,int len){
int i=0;
pthread_mutex_lock(&(fifo->mutex));
if(fifo->size!=fifo->free){
LOGI("current fifo->getP =%d \n",fifo->getP);
for(i=0; ; i++){
*(data+i) =fifo->buf[fifo->getP++];
if(fifo->getP == fifo->size){//用来实现循环
fifo->getP = 0;
}
fifo->free++;
if(fifo->size==fifo->free){
LOGI("the buffer is no data left!\n");
pthread_mutex_unlock(&(fifo->mutex));
return i+1;
}
if(i+1==len){
LOGI("read data finish!\n");
break;
}
}
}
else{
LOGI("the buffer is empty!\n");
pthread_mutex_unlock(&(fifo->mutex));
return 0;
}
pthread_mutex_unlock(&(fifo->mutex));
return len;
}
/*缓冲区被使用容量*/
void fifo8_status(struct FIFO8 *fifo,int *used) {
pthread_mutex_lock(&(fifo->mutex));
*used = fifo->size - fifo->free;
pthread_mutex_unlock(&(fifo->mutex));
}
/*缓冲区剩余容量*/
void fifo8_free(struct FIFO8 *fifo ,int *free) {
pthread_mutex_lock(&(fifo->mutex));
*free = fifo->free;
pthread_mutex_unlock(&(fifo->mutex));
}