当前位置:网站首页>Knowledge consolidation source code implementation 3: buffer ringbuffer
Knowledge consolidation source code implementation 3: buffer ringbuffer
2022-07-06 04:18:00 【yun6853992】
1: Background introduction :
In daily business development , There are many business scenarios using buffers for temporary storage , Such as tcp The bottom layer of each connection maintains a send buffer and a receive buffer .
Achieve one ringbuffer, Make code backup .( You can consider how to treat ringbuffer To expand ?)
// Realization ringbuffer, In fact, it is to apply for a piece of memory , Manage the positions of inserting data and extracting data respectively
typedef struct RINGBUFF_T{
void * data;
unsigned int size;
unsigned int read_pos; // Data start position
unsigned int write_pos; // Data termination location
}ringbuffer_t;
2: Test code :
The code here is for me to test , Achieve one ringbuffer Conduct management .
Only the logical implementation of single thread is considered here , Multithreading needs to be adapted ...
Here, when fetching data , Have a certain design , Consider taking the data of a package ( You can adjust it by yourself ).
2.1:my_ringbuffer.h
#ifndef __RINGBUFFER_H_
#define __RINGBUFFER_H_
typedef struct RINGBUFF_T{
void * data;
unsigned int size;
unsigned int read_pos; // Data start position
unsigned int write_pos; // Data termination location
}ringbuffer_t;
// establish ringbuffer
ringbuffer_t * ringbuffer_create(unsigned int size);
// The destruction ringbuffer
void ringbuffer_destroy(ringbuffer_t * ring_buffer);
// Go to ringbuffer Data stored in write in
int ringbuffer_put(ringbuffer_t * ring_buffer, const char* buffer, unsigned int len);
// Judge whether it is complete data And then deal with it
int ringbuffer_get_len(ringbuffer_t *ring_buffer);
// rely on ringbuffer_get_len Return value request memory , Take out ring_buffer Data in
int ringbuffer_get(ringbuffer_t * ring_buffer, char * buffer, unsigned int len);
// Basic interface Basically no external , But there are uses inside the function
// Reset buffer
void ringbuffer_reset(ringbuffer_t * ring_buffer);
//ringbuffer The amount of memory space that has been used
int ringbuffer_use_len(ringbuffer_t * ring_buffer);
//ringbuffer The size of unused memory
int ringbuffer_space_len(ringbuffer_t * ring_buffer);
// Basic empty and full interfaces
int ringbuffer_isempty(ringbuffer_t * ring_buffer);
int ringbuffer_isfull(ringbuffer_t * ring_buffer);
// int get_ringbuffer_size(ringbuffer_t * ring_buffer);
#endif //__RINGBUFFER_H_
2.2:my_ringbuffer.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "my_ringbuffer.h"
static inline __attribute__((const))
int is_power_of_2(unsigned long n)
{
return (n != 0 && ((n & (n - 1)) == 0));
}
static unsigned long roundup_power_of_two(unsigned long n)
{
if((n & (n-1)) == 0)
return n;
unsigned long maxulong = (unsigned long)((unsigned long)~0);
unsigned long andv = ~(maxulong&(maxulong>>1));
while((andv & n) == 0)
andv = andv>>1;
return andv<<1;
}
// establish ringbuffer
ringbuffer_t * ringbuffer_create(unsigned int size)
{
// Verify the input parameters And is 2 To the power of
if (!is_power_of_2(size)) {
size = roundup_power_of_two(size);
}
ringbuffer_t * ring_buffer;
ring_buffer = (ringbuffer_t*)malloc(sizeof(*ring_buffer));
if(ring_buffer == NULL)
{
printf("create ringbuffer error \n");
return NULL;
}
ring_buffer->data = (void*)malloc(size);
if(ring_buffer->data == NULL)
{
printf("create ringbuffer data error \n");
free(ring_buffer);
return NULL;
}
ring_buffer->size = size;
ring_buffer->read_pos = 0;
ring_buffer->write_pos = 0;
return ring_buffer;
}
// The destruction ringbuffer
void ringbuffer_destroy(ringbuffer_t * ring_buffer)
{
if(ring_buffer)
{
if(ring_buffer->data)
{
free(ring_buffer->data);
ring_buffer->data = NULL;
}
free(ring_buffer);
ring_buffer = NULL;
}
}
// Go to ringbuffer Data stored in write in
int ringbuffer_put(ringbuffer_t * ring_buffer, const char* buffer, unsigned int len)
{
if(ring_buffer->write_pos >=ring_buffer->read_pos &&(len <(ring_buffer->size - ring_buffer->write_pos +ring_buffer->read_pos)))
{
// Copy
if(ring_buffer->size - ring_buffer->write_pos >len)
{
memcpy(ring_buffer->data + ring_buffer->write_pos, buffer, len);
ring_buffer->write_pos += len;
}else
{
unsigned int right_space_len = ring_buffer->size - ring_buffer->write_pos;
memcpy(ring_buffer->data + ring_buffer->write_pos, buffer, right_space_len);
memcpy(ring_buffer->data, buffer+right_space_len, len - right_space_len);
ring_buffer->write_pos = len - right_space_len;
}
return 0;
}
if(ring_buffer->write_pos <ring_buffer->read_pos && (ring_buffer->read_pos - ring_buffer->write_pos) >len)
{
memcpy(ring_buffer->data + ring_buffer->write_pos, buffer, len);
ring_buffer->write_pos += len;
return 0;
}
return -1;
}
// Judge whether it is complete data And then deal with it
int ringbuffer_get_len(ringbuffer_t *ring_buffer)
{
// Yes ringbuffer Judge and analyze the data in If it is complete data Then extract
if(ringbuffer_use_len(ring_buffer) < strlen("FFFF0D0A<header><tail>0D0AFEFE"))
{
printf("ringbuffer data is error [%d], [%ld]\n", ringbuffer_use_len(ring_buffer), strlen("FFFF0D0A<header><tail>0D0AFEFE"));
return -1;
}
// Determine whether it is a terminated field
const char* end_str = "<tail>0D0AFEFE";
char check_end_str[20] = {
0};
if(ring_buffer->write_pos >strlen(end_str))
{
memcpy(check_end_str, ring_buffer->data+ring_buffer->write_pos - (strlen(end_str)), strlen(end_str));
}else
{
unsigned int left_len = ring_buffer->write_pos;
memcpy(check_end_str, ring_buffer->data +ring_buffer->size - (strlen(end_str) - left_len), ring_buffer->size - (strlen(end_str) - left_len));
memcpy(check_end_str + (strlen(end_str) - left_len), ring_buffer->data, left_len);
}
printf("get check_end_str is %s \n", check_end_str);
char * ret_addr = strstr(check_end_str, end_str);
if(ret_addr == NULL)
{
return -1;
}
if(check_end_str - ret_addr != 0)
{
printf("DDDDD :why end string is error");
return -1;
}
return ringbuffer_use_len(ring_buffer);
}
// from ringbuffer Extract data for processing , Determine whether the received character is a terminator , You can deal with it
// Reset after getting data ringbuffer The location of Read
int ringbuffer_get(ringbuffer_t * ring_buffer, char * buffer, unsigned int len)
{
// This is based on ringbuffer_get_len On the basis of , Pass in parameters , Take out the data
int data_len = ringbuffer_use_len(ring_buffer);
if(data_len >= len)
{
printf("para buffer is not enough space \n");
return -1;
}
if(ring_buffer->write_pos >ring_buffer->read_pos )
{
printf("get data from ringbuffer len: [%d] \n", ring_buffer->write_pos - ring_buffer->read_pos);
memcpy(buffer, ring_buffer->data + ring_buffer->read_pos, data_len);
}else
{
memcpy(buffer, ring_buffer->data+ring_buffer->read_pos, ring_buffer->size - ring_buffer->read_pos);
memcpy(buffer+ring_buffer->size - ring_buffer->read_pos, ring_buffer->data, data_len - (ring_buffer->size - ring_buffer->read_pos));
}
ring_buffer->write_pos = 0;
ring_buffer->read_pos = 0;
return 0;
}
// Directly from socket Middle reading data is put into ringbuffer You can also do so.
int ringbuffer_get_from_dev()
{
return 0;
}
// Directly from ringbuffer To extract data from socket Send
int ringbuffer_put_to_dev()
{
return 0;
}
void ringbuffer_reset(ringbuffer_t * ring_buffer)
{
ring_buffer->read_pos = ring_buffer->write_pos = 0;
}
int ringbuffer_use_len(ringbuffer_t * ring_buffer)
{
if(ring_buffer->write_pos >= ring_buffer->read_pos)
{
return ring_buffer->write_pos-ring_buffer->read_pos;
}
return ring_buffer->write_pos + ring_buffer->size - ring_buffer->read_pos;
}
int ringbuffer_space_len(ringbuffer_t * ring_buffer)
{
if(ring_buffer->write_pos >= ring_buffer->read_pos)
{
return ring_buffer->read_pos +(ring_buffer->size - ring_buffer->write_pos);
}
return ring_buffer->read_pos - ring_buffer->write_pos;
}
int ringbuffer_isempty(ringbuffer_t * ring_buffer)
{
return ringbuffer_use_len(ring_buffer) == 0? 0 :-1;
}
int ringbuffer_isfull(ringbuffer_t * ring_buffer)
{
return ringbuffer_space_len(ring_buffer) == 0? 0 :-1;
}
// int get_ringbuffer_size(ringbuffer_t * ring_buffer)
// {
// return ring_buffer->size;
// }
2.3:my_ringbuffer_test.c
/************************************************ info: Yes ringbuffer Do a simple test of the package data: 2022/02/10 author: hlp ************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tcp_ringbuffer.h"
int main()
{
// Apply for one ringbuffer
ringbuffer_t * ringbuff = ringbuffer_create(128);
printf("ringbuffer_create size is : %d \n", ringbuff->size);
printf("ringbuffer isempty [%d] \n", ringbuffer_isempty(ringbuff));
printf("ringbuffer isfull [%d] \n", ringbuffer_isfull(ringbuff));
printf("ringbuffer used len is [%d] \n",ringbuffer_use_len(ringbuff));
printf("ringbuffer space len is [%d] \n", ringbuffer_space_len(ringbuff));
ringbuffer_destroy(ringbuff);
// Judge the basic conditions
ringbuff = ringbuffer_create(129);
printf("ringbuffer_create size is : %d \n", ringbuff->size);
printf("ringbuffer isempty [%d] \n", ringbuffer_isempty(ringbuff));
printf("ringbuffer isfull [%d] \n", ringbuffer_isfull(ringbuff));
printf("ringbuffer used len is [%d] \n",ringbuffer_use_len(ringbuff));
printf("ringbuffer space len is [%d] \n", ringbuffer_space_len(ringbuff));
ringbuffer_destroy(ringbuff);
// to ringbuff Insert a certain amount of data in to view the relevant basic information
ringbuff = ringbuffer_create(129);
const char* str_data = "FFFF0D0A<header><tail>0D0AFEFE";
// to ringbuffer Insert certain data into , Get to view
ringbuffer_put(ringbuff, str_data, strlen(str_data));
printf("set data size is : %lu, ringbuff size is %d \n", strlen(str_data), ringbuff->size);
printf("ringbuffer isempty [%d] \n", ringbuffer_isempty(ringbuff));
printf("ringbuffer isfull [%d] \n", ringbuffer_isfull(ringbuff));
printf("ringbuffer used len is [%d] \n",ringbuffer_use_len(ringbuff));
printf("ringbuffer space len is [%d] \n", ringbuffer_space_len(ringbuff));
int data_len = ringbuffer_get_len(ringbuff);
if(data_len == -1)
{
printf("error of ringbuff data \n");
}else
{
printf("ringbuff data len is %d \n", data_len);
}
char * data_exec;
data_exec = (char*)malloc(data_len +1);
memset(data_exec, 0, data_len +1);
printf("sizeof data_exec is %lu \n", sizeof(data_exec));
ringbuffer_get(ringbuff, data_exec, data_len +1);
printf("ringbuff get data is :%s \n",data_exec);
printf("ringbuffer isempty [%d] \n", ringbuffer_isempty(ringbuff));
printf("ringbuffer isfull [%d] \n", ringbuffer_isfull(ringbuff));
printf("ringbuffer used len is [%d] \n",ringbuffer_use_len(ringbuff));
printf("ringbuffer space len is [%d] \n", ringbuffer_space_len(ringbuff));
ringbuffer_destroy(ringbuff);
if(data_exec !=NULL)
{
free(data_exec);
data_exec = NULL;
}
printf("******************test of more package check***********************\n");
const char* data_str_test = "FFFF0D0A<header><tail>0D0AFEFE";
const char* data_str_test1 = "FFFF0D0A<header>111<tail>0D0AFEFE";
const char* data_str_test2 = "FFFF0D0A<header>222<tail>0D0AFEFE";
const char* data_str_test3 = "FFFF0D0A<header><tail>0D0AFEFE";
const char* data_str_test4 = "FFFF0D0A<header><tail>0D0AFEFE";
const char* data_str_error = "FFFF0D0A<header>test error";
// Try inserting multiple data Can you take it out ?
ringbuff = ringbuffer_create(129);
ringbuffer_put(ringbuff, data_str_test, strlen(data_str_test));
printf("put one data. ringbuffer used len is [%d] \n",ringbuffer_use_len(ringbuff));
printf("put one data. ringbuffer space len is [%d] \n", ringbuffer_space_len(ringbuff));
ringbuffer_put(ringbuff, data_str_test1, strlen(data_str_test1));
printf("put two data. ringbuffer used len is [%d] \n",ringbuffer_use_len(ringbuff));
printf("put two data. ringbuffer space len is [%d] \n", ringbuffer_space_len(ringbuff));
ringbuffer_put(ringbuff, data_str_test2, strlen(data_str_test2));
printf("put three data. ringbuffer used len is [%d] \n",ringbuffer_use_len(ringbuff));
printf("put three data. ringbuffer space len is [%d] \n", ringbuffer_space_len(ringbuff));
printf("ringbuffer is not empty [%d] \n", ringbuffer_isempty(ringbuff));
printf("ringbuffer is not full [%d] \n", ringbuffer_isfull(ringbuff));
int test_get_len = ringbuffer_get_len(ringbuff);
if(test_get_len == -1)
{
printf("error of ringbuff data \n");
}else
{
printf("get ringbuff has data len is %d \n", test_get_len);
}
data_exec = (char*)malloc(test_get_len +1);
memset(data_exec, 0, test_get_len +1);
ringbuffer_get(ringbuff, data_exec, test_get_len +1);
printf("ringbuff get data is :%s \n",data_exec);
printf("get all data used len is [%d] \n",ringbuffer_use_len(ringbuff));
printf("get all data space len is [%d] \n", ringbuffer_space_len(ringbuff));
printf("ringbuffer isempty [%d] \n", ringbuffer_isempty(ringbuff));
printf("ringbuffer is not full [%d] \n", ringbuffer_isfull(ringbuff));
ringbuffer_destroy(ringbuff);
if(data_exec !=NULL)
{
free(data_exec);
data_exec = NULL;
}
ringbuff = ringbuffer_create(129);
ringbuffer_put(ringbuff, data_str_test, strlen(data_str_test));
ringbuffer_put(ringbuff, data_str_error, strlen(data_str_error));
test_get_len = ringbuffer_get_len(ringbuff);
if(test_get_len == -1)
{
printf("error of ringbuff data \n");
}else
{
printf("get ringbuff has data len is %d \n", test_get_len);
}
ringbuffer_put(ringbuff, data_str_test, strlen(data_str_test));
test_get_len = ringbuffer_get_len(ringbuff);
if(test_get_len == -1)
{
printf("error of ringbuff data \n");
}else
{
printf("get ringbuff has data len is %d \n", test_get_len);
}
data_exec = (char*)malloc(test_get_len +1);
memset(data_exec, 0, test_get_len +1);
ringbuffer_get(ringbuff, data_exec, test_get_len +1);
printf("ringbuff get data is :%s \n",data_exec);
printf("get all data used len is [%d] \n",ringbuffer_use_len(ringbuff));
printf("get all data space len is [%d] \n", ringbuffer_space_len(ringbuff));
ringbuffer_destroy(ringbuff);
if(data_exec !=NULL)
{
free(data_exec);
data_exec = NULL;
}
// There won't be write Catch up with read Scene , Unless the design here is not all taken out , Or multithreading
printf("******************* check \n");
return 0;
}
3: Running results
I used it here gcc Compile , of no avail makefile
This is to conform to the specific business format , Yes “FFFF0D0A
This test code is mainly written for tcp Receive buffer business processing considerations .
[email protected]:~/220107/0:test_ringbuffer_tcp_Stickybag$ ./ringbuffer
ringbuffer_create size is : 128
ringbuffer isempty [0]
ringbuffer isfull [-1]
ringbuffer used len is [0]
ringbuffer space len is [128]
ringbuffer_create size is : 256
ringbuffer isempty [0]
ringbuffer isfull [-1]
ringbuffer used len is [0]
ringbuffer space len is [256]
set data size is : 30, ringbuff size is 256
ringbuffer isempty [-1]
ringbuffer isfull [-1]
ringbuffer used len is [30]
ringbuffer space len is [226]
get check_end_str is <tail>0D0AFEFE
ringbuff data len is 30
sizeof data_exec is 8
get data from ringbuffer len: [30]
ringbuff get data is :FFFF0D0A<header><tail>0D0AFEFE
ringbuffer isempty [0]
ringbuffer isfull [-1]
ringbuffer used len is [0]
ringbuffer space len is [256]
******************test of more package check***********************
put one data. ringbuffer used len is [30]
put one data. ringbuffer space len is [226]
put two data. ringbuffer used len is [63]
put two data. ringbuffer space len is [193]
put three data. ringbuffer used len is [96]
put three data. ringbuffer space len is [160]
ringbuffer is not empty [-1]
ringbuffer is not full [-1]
get check_end_str is <tail>0D0AFEFE
get ringbuff has data len is 96
get data from ringbuffer len: [96]
ringbuff get data is :FFFF0D0A<header><tail>0D0AFEFEFFFF0D0A<header>111<tail>0D0AFEFEFFFF0D0A<header>222<tail>0D0AFEFE
get all data used len is [0]
get all data space len is [256]
ringbuffer isempty [0]
ringbuffer is not full [-1]
get check_end_str is der>test error
error of ringbuff data
get check_end_str is <tail>0D0AFEFE
get ringbuff has data len is 86
get data from ringbuffer len: [86]
ringbuff get data is :FFFF0D0A<header><tail>0D0AFEFEFFFF0D0A<header>test errorFFFF0D0A<header><tail>0D0AFEFE
get all data used len is [0]
get all data space len is [256]
******************* check
I started trying to accumulate some common code : Spare in your own code base
More of my knowledge comes from here , I recommend you understand :Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK, Streaming media ,CDN,P2P,K8S,Docker,TCP/IP, coroutines ,DPDK Etc , Learn now
边栏推荐
- P2102 地砖铺设(dfs&贪心)
- Yyds dry goods inventory hcie security Day11: preliminary study of firewall dual machine hot standby and vgmp concepts
- /usr/bin/gzip: 1: ELF: not found/usr/bin/gzip: 3: : not found/usr/bin/gzip: 4: Syntax error:
- Global and Chinese markets for patent hole oval devices 2022-2028: Research Report on technology, participants, trends, market size and share
- Yyds dry goods inventory web components series (VII) -- life cycle of custom components
- Comprehensive ability evaluation system
- [disassembly] a visual air fryer. By the way, analyze the internal circuit
- [PSO] Based on PSO particle swarm optimization, matlab simulation of the calculation of the lowest transportation cost of goods at material points, including transportation costs, agent conversion cos
- SharedPreferences 源码分析
- Global and Chinese markets for fire resistant conveyor belts 2022-2028: Research Report on technology, participants, trends, market size and share
猜你喜欢
查询mysql数据库中各表记录数大小
关于进程、线程、协程、同步、异步、阻塞、非阻塞、并发、并行、串行的理解
Practical development of member management applet 06 introduction to life cycle function and user-defined method
Stable Huawei micro certification, stable Huawei cloud database service practice
Viewing and verifying backup sets using dmrman
Certbot failed to update certificate solution
Deep learning framework installation (tensorflow & pytorch & paddlepaddle)
Recommendation system (IX) PNN model (product based neural networks)
Introduction to hashtable
Solution of storage bar code management system in food industry
随机推荐
[adjustable delay network] development of FPGA based adjustable delay network system Verilog
Path of class file generated by idea compiling JSP page
Explain in simple terms node template parsing error escape is not a function
Unity中几个重要类
2/13 review Backpack + monotonic queue variant
拉格朗日插值法
综合能力测评系统
MySQL transaction isolation level
[tomato assistant installation]
Global and Chinese markets for otolaryngology devices 2022-2028: Research Report on technology, participants, trends, market size and share
Codeforces Round #770 (Div. 2) B. Fortune Telling
Fedora/REHL 安装 semanage
PTA tiantisai l1-078 teacher Ji's return (15 points) detailed explanation
Global and Chinese market of plasma separator 2022-2028: Research Report on technology, participants, trends, market size and share
P3033 [usaco11nov]cow steelchase g (similar to minimum path coverage)
How to execute an SQL statement in MySQL
MySql數據庫root賬戶無法遠程登陸解决辦法
Global and Chinese markets for endoscopic drying storage cabinets 2022-2028: Research Report on technology, participants, trends, market size and share
10個 Istio 流量管理 最常用的例子,你知道幾個?
Execution order of scripts bound to game objects