-
简单图解
缓冲区内部:容量为 capacity 的 内存块 可以看作 长度为 capacity 的 字节数组
读/写指针的变化:版本二中的读写操作函数使用 memcpy 函数复制内存,当写指针在读指针右边时,读取操作最多调用 1 次 memcpy 函数,而写入操作最多调用 2 次 memcpy 函数。当写指针在读指针左边时,读取操作最多调用两次 memcpy 函数,而写入操作最多调用 1 次 memcpy 函数。
-
(读写操作,版本一:函数内部 每次读/写一个字节,操作大量数据时效率很低)
利用 取余运算 使得读/写指针在长度为 capacity 的连续内存空间上循环进行读/写操作 -
(读写操作,版本二:使用 memcpy 函数复制内存 ,效率高)
-
(读写操作,版本三:线程安全版本,可以使用互斥量并委托使用版本二的读写函数作简单实现)
目录
- 头文件 buffer.h
- 源文件 buffer.c
- 简单测试 test.c
1. 头文件 buffer.h
/* buffer.h */
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
struct buffer {
/* 缓冲区容量,用于 malloc 申请内存空间 */
size_t capacity;
/* 累计所有写入操作实际写入的字节总数,其对 capacity 取余即为‘下一个写入位置’ */
size_t byte_writed_count;
/* 累计所有读取操作实际读取的字节总数,其对 capacity 取余即为‘下一个读取位置’ */
size_t byte_readed_count;
/* 指向实际缓冲区 */
char *data;
};
/* 初始化缓冲区 buf,使用指定容量 capacity 申请内存空间 */
void buffer_init(struct buffer *buf, size_t capacity);
/* 版本一:读写函数,内部每次读写一个字节,
将指针 chars 指向的长度为 len 的数据写入缓冲区 buf,
返回值:实际写入的字节数,可能小于 len,当缓冲区可写空间不足时。 */
size_t buffer_write(struct buffer *buf, char *chars, size_t len);
/* 从缓冲区 buf 中读取长度为 len 的数据到指针 chars 指向的空间,
返回值:实际读取的字节数,可能小于 len,当缓冲区没有足够的数据时。 */
size_t buffer_read(struct buffer *buf, char *chars, size_t len);
/* 版本二:读/写函数,内部使用 memcpy 函数进行内存复制,效率高 */
size_t buffer_write_by_memcpy(struct buffer *buf, char *chars, size_t len);
size_t buffer_read_by_memcpy(struct buffer *buf, char *chars, size_t len);
/* (待实现)版本三:线程安全版本
(待实现)线程安全写,应与线程安全读 buffer_pread 配合使用 */
// size_t buffer_pwrite(struct buffer *buf, char *chars, size_t len);
/* (待实现)线程安全读,应与线程安全写 buffer_pwrite 配合使用 */
// size_t buffer_pread(struct buffer *buf, char *chars, size_t len);
/* 返回值:缓冲区中已缓存的(可读取)字节数 */
size_t buffer_available_read(struct buffer *buf);
/* 返回值:缓冲区可写入的字节数 */
size_t buffer_available_write(struct buffer *buf);
/* 返回值:缓冲区容量 capacity */
size_t buffer_capacity(struct buffer *buf);
/* 清空缓冲区,实际上仅仅重置读/写指针,缓冲区容量不变 */
void buffer_clear(struct buffer *buf);
/* 销毁/释放缓冲区,free 内存资源 */
void buffer_destroy(struct buffer *buf);
/* 简单错误日志输出至 stderr */
void errlog(const char *msg);
/* 简单日志输出至 stdout */
void infolog(const char *msg);
2. 源文件 buffer.c
/* buffer.c */
#include "buffer.h"
// 初始化缓冲区 buf,使用指定容量 capacity 申请内存空间
void buffer_init(struct buffer *buf, size_t capacity){
if(buf == NULL || capacity <= 0){
errlog("Invalid argument.");
// error
errno = EINVAL; // // Invalid argument
exit(EXIT_FAILURE);
}
// 实际分配内存
buf -> data = malloc(capacity);
if(buf -> data == NULL){
errlog("Cannot allocate memory: unknown error.");
// error
errno = ENOMEM;
exit(EXIT_FAILURE);
}
buf -> capacity = capacity;
buf -> byte_readed_count = 0;
buf -> byte_writed_count = 0