linux内核--使用内核队列实现ringbuffer(续)
来源:互联网 发布:mrj频道 知乎 编辑:程序博客网 时间:2024/06/08 06:03
一、ring buffer
在以前的一篇文章--网络编程中接受缓冲的ringbuf的简单实现介绍了一个自己写的ringbuffer,其实原理和linux内核中的队列很相似,思想是一样的,只不过处理的没有内核那么恰当巧妙,这里也可以使用linux内核中的队列实现之。
/**@brief 仿照linux kfifo写的ring buffer *@atuher Anker date:2013-12-18* ring_buffer.h * */#ifndef KFIFO_HEADER_H #define KFIFO_HEADER_H#include <inttypes.h>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <assert.h>//判断x是否是2的次方#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))//取a和b中最小值#define min(a, b) (((a) < (b)) ? (a) : (b))struct ring_buffer{ void *buffer; //缓冲区 uint32_t size; //大小 uint32_t in; //入口位置 uint32_t out; //出口位置 pthread_mutex_t *f_lock; //互斥锁};//初始化缓冲区struct ring_buffer* ring_buffer_init(void *buffer, uint32_t size, pthread_mutex_t *f_lock){ assert(buffer); struct ring_buffer *ring_buf = NULL; if (!is_power_of_2(size)) { fprintf(stderr,"size must be power of 2.\n"); return ring_buf; } ring_buf = (struct ring_buffer *)malloc(sizeof(struct ring_buffer)); if (!ring_buf) { fprintf(stderr,"Failed to malloc memory,errno:%u,reason:%s", errno, strerror(errno)); return ring_buf; } memset(ring_buf, 0, sizeof(struct ring_buffer)); ring_buf->buffer = buffer; ring_buf->size = size; ring_buf->in = 0; ring_buf->out = 0; ring_buf->f_lock = f_lock; return ring_buf;}//释放缓冲区void ring_buffer_free(struct ring_buffer *ring_buf){ if (ring_buf) { if (ring_buf->buffer) { free(ring_buf->buffer); ring_buf->buffer = NULL; } free(ring_buf); ring_buf = NULL; }}//缓冲区的长度uint32_t __ring_buffer_len(const struct ring_buffer *ring_buf){ return (ring_buf->in - ring_buf->out);}//从缓冲区中取数据uint32_t __ring_buffer_get(struct ring_buffer *ring_buf, void * buffer, uint32_t size){ assert(ring_buf || buffer); uint32_t len = 0; size = min(size, ring_buf->in - ring_buf->out); /* first get the data from fifo->out until the end of the buffer */ len = min(size, ring_buf->size - (ring_buf->out & (ring_buf->size - 1))); memcpy(buffer, ring_buf->buffer + (ring_buf->out & (ring_buf->size - 1)), len); /* then get the rest (if any) from the beginning of the buffer */ memcpy(buffer + len, ring_buf->buffer, size - len); ring_buf->out += size; return size;}//向缓冲区中存放数据uint32_t __ring_buffer_put(struct ring_buffer *ring_buf, void *buffer, uint32_t size){ assert(ring_buf || buffer); uint32_t len = 0; size = min(size, ring_buf->size - ring_buf->in + ring_buf->out); /* first put the data starting from fifo->in to buffer end */ len = min(size, ring_buf->size - (ring_buf->in & (ring_buf->size - 1))); memcpy(ring_buf->buffer + (ring_buf->in & (ring_buf->size - 1)), buffer, len); /* then put the rest (if any) at the beginning of the buffer */ memcpy(ring_buf->buffer, buffer + len, size - len); ring_buf->in += size; return size;}uint32_t ring_buffer_len(const struct ring_buffer *ring_buf){ uint32_t len = 0; pthread_mutex_lock(ring_buf->f_lock); len = __ring_buffer_len(ring_buf); pthread_mutex_unlock(ring_buf->f_lock); return len;}uint32_t ring_buffer_get(struct ring_buffer *ring_buf, void *buffer, uint32_t size){ uint32_t ret; pthread_mutex_lock(ring_buf->f_lock); ret = __ring_buffer_get(ring_buf, buffer, size); //buffer中没有数据 if (ring_buf->in == ring_buf->out) ring_buf->in = ring_buf->out = 0; pthread_mutex_unlock(ring_buf->f_lock); return ret;}uint32_t ring_buffer_put(struct ring_buffer *ring_buf, void *buffer, uint32_t size){ uint32_t ret; pthread_mutex_lock(ring_buf->f_lock); ret = __ring_buffer_put(ring_buf, buffer, size); pthread_mutex_unlock(ring_buf->f_lock); return ret;}#endif
采用多线程模拟生产者和消费者编写测试程序,如下所示:
/**@brief ring buffer测试程序,创建两个线程,一个生产者,一个消费者。 * 生产者每隔1秒向buffer中投入数据,消费者每隔2秒去取数据。 *@atuher Anker date:2013-12-18 * */#include "ring_buffer.h"#include <pthread.h>#include <time.h>#define BUFFER_SIZE 1024 * 1024typedef struct student_info{ uint64_t stu_id; uint32_t age; uint32_t score;}student_info;void print_student_info(const student_info *stu_info){ assert(stu_info); printf("id:%lu\t",stu_info->stu_id); printf("age:%u\t",stu_info->age); printf("score:%u\n",stu_info->score);}student_info * get_student_info(time_t timer){ student_info *stu_info = (student_info *)malloc(sizeof(student_info)); if (!stu_info) { fprintf(stderr, "Failed to malloc memory.\n"); return NULL; } srand(timer); stu_info->stu_id = 10000 + rand() % 9999; stu_info->age = rand() % 30; stu_info->score = rand() % 101; print_student_info(stu_info); return stu_info;}void * consumer_proc(void *arg){ struct ring_buffer *ring_buf = (struct ring_buffer *)arg; student_info stu_info; while(1) { sleep(2); printf("------------------------------------------\n"); printf("get a student info from ring buffer.\n"); ring_buffer_get(ring_buf, (void *)&stu_info, sizeof(student_info)); printf("ring buffer length: %u\n", ring_buffer_len(ring_buf)); print_student_info(&stu_info); printf("------------------------------------------\n"); } return (void *)ring_buf;}void * producer_proc(void *arg){ time_t cur_time; struct ring_buffer *ring_buf = (struct ring_buffer *)arg; while(1) { time(&cur_time); srand(cur_time); int seed = rand() % 11111; printf("******************************************\n"); student_info *stu_info = get_student_info(cur_time + seed); printf("put a student info to ring buffer.\n"); ring_buffer_put(ring_buf, (void *)stu_info, sizeof(student_info)); printf("ring buffer length: %u\n", ring_buffer_len(ring_buf)); printf("******************************************\n"); sleep(1); } return (void *)ring_buf;}int consumer_thread(void *arg){ int err; pthread_t tid; err = pthread_create(&tid, NULL, consumer_proc, arg); if (err != 0) { fprintf(stderr, "Failed to create consumer thread.errno:%u, reason:%s\n", errno, strerror(errno)); return -1; } return tid;}int producer_thread(void *arg){ int err; pthread_t tid; err = pthread_create(&tid, NULL, producer_proc, arg); if (err != 0) { fprintf(stderr, "Failed to create consumer thread.errno:%u, reason:%s\n", errno, strerror(errno)); return -1; } return tid;}int main(){ void * buffer = NULL; uint32_t size = 0; struct ring_buffer *ring_buf = NULL; pthread_t consume_pid, produce_pid; pthread_mutex_t *f_lock = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); if (pthread_mutex_init(f_lock, NULL) != 0) { fprintf(stderr, "Failed init mutex,errno:%u,reason:%s\n", errno, strerror(errno)); return -1; } buffer = (void *)malloc(BUFFER_SIZE); if (!buffer) { fprintf(stderr, "Failed to malloc memory.\n"); return -1; } size = BUFFER_SIZE; ring_buf = ring_buffer_init(buffer, size, f_lock); if (!ring_buf) { fprintf(stderr, "Failed to init ring buffer.\n"); return -1; }#if 0 student_info *stu_info = get_student_info(638946124); ring_buffer_put(ring_buf, (void *)stu_info, sizeof(student_info)); stu_info = get_student_info(976686464); ring_buffer_put(ring_buf, (void *)stu_info, sizeof(student_info)); ring_buffer_get(ring_buf, (void *)stu_info, sizeof(student_info)); print_student_info(stu_info);#endif printf("multi thread test.......\n"); produce_pid = producer_thread((void*)ring_buf); consume_pid = consumer_thread((void*)ring_buf); pthread_join(produce_pid, NULL); pthread_join(consume_pid, NULL); ring_buffer_free(ring_buf); free(f_lock); return 0;}测试结果如下:
1 0
- linux内核--使用内核队列实现ringbuffer(续)
- linux内核队列实现
- Linux内核通用队列的使用笔记(读linux内核设计与实现)
- linux 下内核中消息队列实现
- Linux 内核的队列实现--kfifo
- Linux 内核的队列实现--kfifo
- linux内核的队列实现移植
- linux内核下等待队列的使用
- Linux内核 - 等待队列的使用
- Linux内核-工作队列的使用
- linux内核等待队列的使用
- linux 内核下等待队列的使用
- Linux内核 工作队列的使用
- 《Linux内核设计与实现》读书笔记(六)- 内核数据结构之链表与队列
- LINUX内核-等待队列
- linux 内核等待队列
- linux 内核 队列 kfifo
- linux 内核 工作队列
- 关于java的一些名词
- linux下java安装
- android通讯录 MIMETYPE DATA1~DATA15
- 在iOS中创建静态库
- 苹果Xcode帮助文档阅读指南
- linux内核--使用内核队列实现ringbuffer(续)
- Extensible XML authoring
- Servlet详解---取得其他内置对象
- ffmpeg解码视频
- Sharepoint 2010 用VS定制Master,并且每个Web应用同一个Master
- gluProject与gluUnProject
- Android 按两次返回键退出
- linux下jetty的安装
- 串的模式匹配算法