当前位置:网站首页>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
边栏推荐
- IDEA编译JSP页面生成的class文件路径
- math_ Derivative function derivation of limit & differential & derivative & derivative / logarithmic function (derivative definition limit method) / derivative formula derivation of exponential functi
- Figure application details
- 查询mysql数据库中各表记录数大小
- 2/13 review Backpack + monotonic queue variant
- MySql數據庫root賬戶無法遠程登陸解决辦法
- Python book learning notes - Chapter 09 section 01 create and use classes
- Patent | subject classification method based on graph convolution neural network fusion of multiple human brain maps
- P2022 interesting numbers (binary & digit DP)
- P3500 [POI2010]TES-Intelligence Test(二分&离线)
猜你喜欢
MySql數據庫root賬戶無法遠程登陸解决辦法
电脑钉钉怎么调整声音
Yyds dry goods inventory hcie security Day11: preliminary study of firewall dual machine hot standby and vgmp concepts
Redis (replicate dictionary server) cache
Stc8h development (XII): I2C drive AT24C08, at24c32 series EEPROM storage
满足多元需求:捷码打造3大一站式开发套餐,助力高效开发
Data processing methods - smote series and adasyn
coreldraw2022新版本新功能介绍cdr2022
综合能力测评系统
Le compte racine de la base de données MySQL ne peut pas se connecter à distance à la solution
随机推荐
2/12 didn't learn anything
How to solve the problem of slow downloading from foreign NPM official servers—— Teach you two ways to switch to Taobao NPM image server
图应用详解
In depth MySQL transactions, stored procedures and triggers
P3033 [usaco11nov]cow steelchase g (similar to minimum path coverage)
SharedPreferences 源码分析
深入浅出node模板解析错误escape is not a function
Mysql database storage engine
Solve the compilation problem of "c2001: line breaks in constants"
Understanding of processes, threads, coroutines, synchronization, asynchrony, blocking, non blocking, concurrency, parallelism, and serialization
Global and Chinese markets for medical gas manifolds 2022-2028: Research Report on technology, participants, trends, market size and share
When debugging after pycharm remote server is connected, trying to add breakpoint to file that does not exist: /data appears_ sda/d:/segmentation
CertBot 更新证书失败解决
Patent | subject classification method based on graph convolution neural network fusion of multiple human brain maps
P2102 地砖铺设(dfs&贪心)
Practical development of member management applet 06 introduction to life cycle function and user-defined method
MySQL transaction isolation level
DM8 backup set deletion
Ipv4中的A 、B、C类网络及子网掩码
[disassembly] a visual air fryer. By the way, analyze the internal circuit