当前位置:网站首页>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
边栏推荐
- E. Best Pair
- Basic knowledge of binary tree, BFC, DFS
- 10個 Istio 流量管理 最常用的例子,你知道幾個?
- PTA tiantisai l1-078 teacher Ji's return (15 points) detailed explanation
- 10个 Istio 流量管理 最常用的例子,你知道几个?
- R note prophet
- P2648 make money
- Guitar Pro 8.0最详细全面的更新内容及全部功能介绍
- Global and Chinese markets for MRI safe implants 2022-2028: technology, participants, trends, market size and share Research Report
- [adjustable delay network] development of FPGA based adjustable delay network system Verilog
猜你喜欢
![[FPGA tutorial case 11] design and implementation of divider based on vivado core](/img/39/f337510c2647d365603a8485583a20.png)
[FPGA tutorial case 11] design and implementation of divider based on vivado core

Figure application details

When debugging after pycharm remote server is connected, trying to add breakpoint to file that does not exist: /data appears_ sda/d:/segmentation

What is the difference between gateway address and IP address in tcp/ip protocol?

IDEA编译JSP页面生成的class文件路径

Comprehensive ability evaluation system

综合能力测评系统

During pycharm debugging, the view is read only and pause the process to use the command line appear on the console input

Slow SQL fetching and analysis of MySQL database

Basic use of MySQL (it is recommended to read and recite the content)
随机推荐
Global and Chinese markets for fire resistant conveyor belts 2022-2028: Research Report on technology, participants, trends, market size and share
View 工作流程
P2102 地砖铺设(dfs&贪心)
DM8 archive log file manual switching
拉格朗日插值法
Solve the compilation problem of "c2001: line breaks in constants"
The value of two date types is subtracted and converted to seconds
Yyds dry goods inventory hcie security Day11: preliminary study of firewall dual machine hot standby and vgmp concepts
食品行业仓储条码管理系统解决方案
Comprehensive ability evaluation system
2328. Number of incremental paths in the grid graph (memory search)
JVM garbage collector concept
Solution to the problem that the root account of MySQL database cannot be logged in remotely
QML和QWidget混合开发(初探)
729. My schedule I (set or dynamic open point segment tree)
Stable Huawei micro certification, stable Huawei cloud database service practice
2327. Number of people who know secrets (recursive)
lora网关以太网传输
. Net interprocess communication
牛顿插值法