linux核心--使用核心佇列實現ringbuffer
ringbuffer
1.instance analysis
/**@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>
#include <unistd.h>
#define BUFFER_SIZE 1024 * 1024
typedef 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;
}
pthread_join(tid, NULL);
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;
}
//pthread_join(tid, NULL);
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);
printf("multi thread test2xxxxxxx.......\n");
ring_buffer_free(ring_buf);
free(f_lock);
printf("multi thread test3xxxxxxx.......\n");
return 0;
}
#!/bin/sh
gcc ring_buffer.c -o ring_buffer -lpthread
參考程式碼linux核心–使用核心佇列實現ringbuffer中有段錯誤,已修正
相關文章
- Linux 核心 tasklet 機制和工作佇列Linux佇列
- 【Linux核心設計與實現】Linux核心簡介Linux
- 《Linux核心設計與實現》學習【5】—— 核心同步Linux
- linux核心設計與實現Linux
- Linux核心中的軟中斷、tasklet和工作佇列詳解Linux佇列
- 使用 RabbitMQ 實現延時佇列MQ佇列
- 使用LinkedList實現安全佇列佇列
- Linux程式排程核心實現分析Linux
- Promise核心實現Promise
- 使用陣列實現環形佇列Scala版本陣列佇列
- 通過佇列實現棧OR通過棧實現佇列佇列
- GCD之佇列的實現和使用GC佇列
- 使用佇列實現楊輝三角佇列
- 使用C#實現順序佇列C#佇列
- 使用RabbitMq原生實現延遲佇列MQ佇列
- javascript實現佇列JavaScript佇列
- Linux共享記憶體的核心實現Linux記憶體
- epoll核心實現分析
- C 語言實現使用靜態陣列實現迴圈佇列陣列佇列
- C 語言實現使用動態陣列實現迴圈佇列陣列佇列
- 佇列的一種實現:迴圈佇列佇列
- Linux核心之 核心同步Linux
- ArrayDeque雙端佇列 使用&實現原理分析佇列
- 使用Spring Boot實現訊息佇列Spring Boot佇列
- 9. 題目:對佇列實現棧&用棧實現佇列佇列
- 佇列(Queue)-c實現佇列
- 用 Rust 實現佇列Rust佇列
- 用佇列實現棧佇列
- 用棧實現佇列佇列
- Python佇列的三種佇列實現方法Python佇列
- Docker的核心實現原理Docker
- Linux核心使用gdb除錯Linux除錯
- Go中使用Redis實現訊息佇列教程GoRedis佇列
- 認識linux核心(linux核心的作用)Linux
- 鏈式佇列—用連結串列來實現佇列佇列
- Redis實現任務佇列、優先順序佇列Redis佇列
- linux核心命令列引數速查手冊Linux命令列
- Redis使用ZSET實現訊息佇列使用總結二Redis佇列