马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
目次
链式缓冲区(Chain Buffer)简介
为什么选择链式缓冲区?
代码分析
1. 头文件与范例界说
2. 布局体界说
3. 宏界说与常量
4. 环形缓冲区的根本操纵
5. 其他辅助函数
6. 数据读写操纵的详细实现
7. 总结
8. 团结之前的内容
9. 详细应用分析
10. 综合应用
11. 总结
链式缓冲区(Chain Buffer)简介
链式缓冲区是一种通过链接多个缓冲区块来动态管理数据的布局。相比于固定巨细的环形缓冲区,链式缓冲区具有更高的机动性和可扩展性,特殊实用于须要处置惩罚差别巨细数据包的场景。它通过将数据分散存储在多个缓冲区块中,镌汰了内存浪费和数据移动的需求。
为什么选择链式缓冲区?
- 机动性和可扩展性:链式缓冲区可以或许动态地添加或移除缓冲区块,顺应差别的数据量需求。
- 镌汰数据移动:通太过散存储数据,克制了大规模的数据拷贝操纵,进步了数据处置惩罚服从。
- 高效内存利用:根据实际数据量动态分配缓冲区块,镌汰了内存浪费。
代码分析
让我们渐渐分析你提供的链式缓冲区代码,明白其各个部分的功能和实现细节。
1. 头文件与范例界说
- #ifndef _chain_buffer_h
- #define _chain_buffer_h
- #include <stdint.h>
- typedef struct buf_chain_s buf_chain_t;
- typedef struct buffer_s buffer_t;
- // Function declarations
- buffer_t * buffer_new(uint32_t sz);
- uint32_t buffer_len(buffer_t *buf);
- int buffer_add(buffer_t *buf, const void *data, uint32_t datlen);
- int buffer_remove(buffer_t *buf, void *data, uint32_t datlen);
- int buffer_drain(buffer_t *buf, uint32_t len);
- void buffer_free(buffer_t *buf);
- int buffer_search(buffer_t *buf, const char* sep, const int seplen);
- uint8_t * buffer_write_atmost(buffer_t *p);
- #endif
复制代码 1.1 头文件掩护符
- #ifndef _chain_buffer_h
- #define _chain_buffer_h
- ...
- #endif
复制代码
1.2 范例界说
- typedef struct buf_chain_s buf_chain_t;
- typedef struct buffer_s buffer_t;
复制代码
- 作用:为布局体 buf_chain_s 和 buffer_s 界说别名 buf_chain_t 和 buffer_t,简化后续代码的誊写。
2. 布局体界说
- struct buf_chain_s {
- struct buf_chain_s *next;
- uint32_t buffer_len;
- uint32_t misalign;
- uint32_t off;
- uint8_t *buffer;
- };
- struct buffer_s {
- buf_chain_t *first;
- buf_chain_t *last;
- buf_chain_t **last_with_datap;
- uint32_t total_len;
- uint32_t last_read_pos; // for sep read
- };
复制代码 2.1 buf_chain_s 布局体
- next (struct buf_chain_s *):指向下一个缓冲区块,实现链式布局。
- buffer_len (uint32_t):缓冲区块的总巨细,以字节为单元。
- misalign (uint32_t):缓冲区块的未对齐偏移量,用于优化内存访问。
- off (uint32_t):当前缓冲区块中有用数据的长度,以字节为单元。
- buffer (uint8_t *):指向实际数据存储区的指针。
2.2 buffer_s 布局体
- first (buf_chain_t *):链表的第一个缓冲区块。
- last (buf_chain_t *):链表的末了一个缓冲区块。
- last_with_datap (buf_chain_t **):指向链表中末了一个有数据的缓冲区块的指针的指针,用于快速定位添加新数据的位置。
- total_len (uint32_t):缓冲区中当前存储的总数据量,以字节为单元。
- last_read_pos (uint32_t):用于分隔符读取的前次读取位置,优化搜刮性能。
3. 宏界说与常量
- #define CHAIN_SPACE_LEN(ch) ((ch)->buffer_len - ((ch)->misalign + (ch)->off))
- #define MIN_BUFFER_SIZE 1024
- #define MAX_TO_COPY_IN_EXPAND 4096
- #define BUFFER_CHAIN_MAX_AUTO_SIZE 4096
- #define MAX_TO_REALIGN_IN_EXPAND 2048
- #define BUFFER_CHAIN_MAX 16*1024*1024 // 16M
- #define BUFFER_CHAIN_EXTRA(t, c) (t *)((buf_chain_t *)(c) + 1)
- #define BUFFER_CHAIN_SIZE sizeof(buf_chain_t)
复制代码
- CHAIN_SPACE_LEN(ch):盘算缓冲区块 ch 中剩余的可用空间。
- MIN_BUFFER_SIZE:缓冲区块的最小巨细,设置为1024字节。
- MAX_TO_COPY_IN_EXPAND:扩展缓冲区时最多复制的字节数。
- BUFFER_CHAIN_MAX_AUTO_SIZE:主动扩展缓冲区块的最大巨细。
- MAX_TO_REALIGN_IN_EXPAND:扩展时最大允许重新对齐的字节数。
- BUFFER_CHAIN_MAX:缓冲区块的最大巨细,设置为16MB。
- BUFFER_CHAIN_EXTRA(t, c):宏,用于获取缓冲区块中的实际数据存储区的指针。
- BUFFER_CHAIN_SIZE:缓冲区块布局体的巨细。
4. 环形缓冲区的根本操纵
4.1 创建缓冲区
- buffer_t * buffer_new(uint32_t sz) {
- (void)sz;
- buffer_t * buf = (buffer_t *) malloc(sizeof(buffer_t));
- if (!buf) {
- return NULL;
- }
- memset(buf, 0, sizeof(*buf));
- buf->last_with_datap = &buf->first;
- return buf;
- }
复制代码
- 功能:创建并初始化一个新的链式缓冲区。
- 步调:
- 分配内存,初始化布局体 buffer_t。
- 利用 memset 清零布局体成员。
- 初始化 last_with_datap 指针为指向 first,体现当前没有数据存储。
- 返回缓冲区指针。
留意:固然函数吸收一个巨细参数 sz,但在当前实现中未利用(通过 (void)sz; 忽略)。这是由于链式缓冲区通过动态添加缓冲区块来顺应差别的数据量需求,而不依靠于单一的固定巨细。
4.2 获取缓冲区长度
- uint32_t buffer_len(buffer_t *buf) {
- return buf->total_len;
- }
复制代码
- 功能:返回缓冲区中当前存储的数据长度。
- 实现:直接返回 total_len。
4.3 开释缓冲区
- void buffer_free(buffer_t *buf) {
- buf_chain_free_all(buf->first);
- }
复制代码
- 功能:开释链式缓冲区中的全部缓冲区块,并开释缓冲区布局体本身。
- 步调:
- 调用 buf_chain_free_all 开释全部缓冲区块。
- 留意:当前实现未开释 buffer_t 本身的内存,大概须要在调用者中举行开释。
4.4 添加数据到缓冲区
- int buffer_add(buffer_t *buf, const void *data_in, uint32_t datlen) {
- buf_chain_t *chain, *tmp;
- const uint8_t *data = data_in;
- uint32_t remain, to_alloc;
- int result = -1;
- if (datlen > BUFFER_CHAIN_MAX - buf->total_len) {
- goto done;
- }
- if (*buf->last_with_datap == NULL) {
- chain = buf->last;
- } else {
- chain = *buf->last_with_datap;
- }
- if (chain == NULL) {
- chain = buf_chain_insert_new(buf, datlen);
- if (!chain)
- goto done;
- }
- remain = chain->buffer_len - chain->misalign - chain->off;
- if (remain >= datlen) {
- memcpy(chain->buffer + chain->misalign + chain->off, data, datlen);
- chain->off += datlen;
- buf->total_len += datlen;
- // buf->n_add_for_cb += datlen;
- goto out;
- } else if (buf_chain_should_realign(chain, datlen)) {
- buf_chain_align(chain);
- memcpy(chain->buffer + chain->off, data, datlen);
- chain->off += datlen;
- buf->total_len += datlen;
- // buf->n_add_for_cb += datlen;
- goto out;
- }
- to_alloc = chain->buffer_len;
- if (to_alloc <= BUFFER_CHAIN_MAX_AUTO_SIZE/2)
- to_alloc <<= 1;
- if (datlen > to_alloc)
- to_alloc = datlen;
- tmp = buf_chain_new(to_alloc);
- if (tmp == NULL)
- goto done;
- if (remain) {
- memcpy(chain->buffer + chain->misalign + chain->off, data, remain);
- chain->off += remain;
- buf->total_len += remain;
- // buf->n_add_for_cb += remain;
- }
- data += remain;
- datlen -= remain;
- memcpy(tmp->buffer, data, datlen);
- tmp->off = datlen;
- buf_chain_insert(buf, tmp);
- // buf->n_add_for_cb += datlen;
- out:
- result = 0;
- done:
- return result;
- }
复制代码
- 功能:将数据添加到链式缓冲区中。
- 步调:
- 查抄缓冲区是否已满:
- 假如要添加的数据 datlen 凌驾缓冲区的最大允许长度(BUFFER_CHAIN_MAX),则返回错误 -1。
- 定位当前可用的缓冲区块:
- 假如 last_with_datap 指向 NULL,
|