当前位置:网站首页>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
边栏推荐
- Global and Chinese market of aircraft anti icing and rain protection systems 2022-2028: Research Report on technology, participants, trends, market size and share
- hashlimit速率控制
- Understanding of processes, threads, coroutines, synchronization, asynchrony, blocking, non blocking, concurrency, parallelism, and serialization
- Query the number and size of records in each table in MySQL database
- How does computer nail adjust sound
- 2/10 parallel search set +bfs+dfs+ shortest path +spfa queue optimization
- [adjustable delay network] development of FPGA based adjustable delay network system Verilog
- Use js to complete an LRU cache
- Le compte racine de la base de données MySQL ne peut pas se connecter à distance à la solution
- Global and Chinese markets for patent hole oval devices 2022-2028: Research Report on technology, participants, trends, market size and share
猜你喜欢

In depth MySQL transactions, stored procedures and triggers

Basic use of MySQL (it is recommended to read and recite the content)

How to solve the problem of slow downloading from foreign NPM official servers—— Teach you two ways to switch to Taobao NPM image server
![[adjustable delay network] development of FPGA based adjustable delay network system Verilog](/img/82/7ff7f99f5164f91fab7713978cf720.png)
[adjustable delay network] development of FPGA based adjustable delay network system Verilog
![[Zhao Yuqiang] deploy kubernetes cluster with binary package](/img/45/6777fa919386e526dbb0d2c808a7f2.jpg)
[Zhao Yuqiang] deploy kubernetes cluster with binary package

Solution of storage bar code management system in food industry

Lora gateway Ethernet transmission

Viewing and verifying backup sets using dmrman

Le compte racine de la base de données MySQL ne peut pas se connecter à distance à la solution

lora网关以太网传输
随机推荐
题解:《单词覆盖还原》、《最长连号》、《小玉买文具》、《小玉家的电费》
Use js to complete an LRU cache
HotSpot VM
Interface idempotency
Brief tutorial for soft exam system architecture designer | general catalog
Viewing and verifying backup sets using dmrman
How to solve the problem of slow downloading from foreign NPM official servers—— Teach you two ways to switch to Taobao NPM image server
10 exemples les plus courants de gestion du trafic istio, que savez - vous?
Stable Huawei micro certification, stable Huawei cloud database service practice
. Net interprocess communication
Understanding of processes, threads, coroutines, synchronization, asynchrony, blocking, non blocking, concurrency, parallelism, and serialization
lora网关以太网传输
How does technology have the ability to solve problems perfectly
The value of two date types is subtracted and converted to seconds
DM8 backup set deletion
【HBZ分享】ArrayList的增删慢查询快的原因
Global and Chinese markets for medical gas manifolds 2022-2028: Research Report on technology, participants, trends, market size and share
1291_ Add timestamp function in xshell log
Solve the compilation problem of "c2001: line breaks in constants"
Class A, B, C networks and subnet masks in IPv4