博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Swoole 源码分析——内存模块之swBuffer
阅读量:6879 次
发布时间:2019-06-26

本文共 3808 字,大约阅读时间需要 12 分钟。

前言

swoole 中数据的接受与发送(例如 reactor 线程接受客户端消息、发送给客户端的消息、接受到的来自 worker 的消息、要发送给 worker 的消息等等)都要涉及到缓冲区,swoole 中的缓冲区实现是 swBuffer,实际上是一个单链表。

swBuffer 的数据结构

  • swBuffer 数据结构中 trunk_num 是链表元素的个数,trunk_sizeswBuffer 缓冲区创建时,链表元素约定的大小(实际大小不一定是这个值),length 是实际上缓冲区占用的内存总大小。
  • swBuffer_trunk 中的 type 有三种,分别应用于:缓存数据、发送文件、提醒连接关闭三种情景。length 指的是元素的内存大小。
enum swBufferChunk{    SW_CHUNK_DATA,    SW_CHUNK_SENDFILE,    SW_CHUNK_CLOSE,};typedef struct _swBuffer_trunk{    uint32_t type;    uint32_t length;    uint32_t offset;    union    {        void *ptr;        struct        {            uint32_t val1;            uint32_t val2;        } data;    } store;    uint32_t size;    void (*destroy)(struct _swBuffer_trunk *chunk);    struct _swBuffer_trunk *next;} swBuffer_trunk;typedef struct _swBuffer{    int fd;    uint8_t trunk_num; //trunk数量    uint16_t trunk_size;    uint32_t length;    swBuffer_trunk *head;    swBuffer_trunk *tail;} swBuffer;

swBuffer 的创建

swBuffer 的创建很简单,只是初始化整个 swBufferheader 头元素而已:

swBuffer* swBuffer_new(int trunk_size){    swBuffer *buffer = sw_malloc(sizeof(swBuffer));    if (buffer == NULL)    {        swWarn("malloc for buffer failed. Error: %s[%d]", strerror(errno), errno);        return NULL;    }    bzero(buffer, sizeof(swBuffer));    buffer->trunk_size = trunk_size;    return buffer;}

swBuffer 内存的申请

swBuffer 内存的申请逻辑也很简单,按照传入的 size 参数为链表元素申请内存,初始化成员变量,然后将链表元素放到链表的尾部即可:

int swBuffer_append(swBuffer *buffer, void *data, uint32_t size){    swBuffer_trunk *chunk = swBuffer_new_trunk(buffer, SW_CHUNK_DATA, size);    if (chunk == NULL)    {        return SW_ERR;    }    buffer->length += size;    chunk->length = size;    memcpy(chunk->store.ptr, data, size);    swTraceLog(SW_TRACE_BUFFER, "trunk_n=%d|size=%d|trunk_len=%d|trunk=%p", buffer->trunk_num, size,            chunk->length, chunk);    return SW_OK;}swBuffer_trunk *swBuffer_new_trunk(swBuffer *buffer, uint32_t type, uint32_t size){    swBuffer_trunk *chunk = sw_malloc(sizeof(swBuffer_trunk));    if (chunk == NULL)    {        swWarn("malloc for trunk failed. Error: %s[%d]", strerror(errno), errno);        return NULL;    }    bzero(chunk, sizeof(swBuffer_trunk));    //require alloc memory    if (type == SW_CHUNK_DATA && size > 0)    {        void *buf = sw_malloc(size);        if (buf == NULL)        {            swWarn("malloc(%d) for data failed. Error: %s[%d]", size, strerror(errno), errno);            sw_free(chunk);            return NULL;        }        chunk->size = size;        chunk->store.ptr = buf;    }    chunk->type = type;    buffer->trunk_num ++;    if (buffer->head == NULL)    {        buffer->tail = buffer->head = chunk;    }    else    {        buffer->tail->next = chunk;        buffer->tail = chunk;    }    return chunk;}

获取 swBuffer 的元素

swBuffer 缓冲区拿数据只能从 head 中获取:

#define swBuffer_get_trunk(buffer)   (buffer->head)

swBuffer 元素的 pop

获取了缓冲区的元素之后,就要相应删除 head 链表元素:

void swBuffer_pop_trunk(swBuffer *buffer, swBuffer_trunk *chunk){    if (chunk->next == NULL)    {        buffer->head = NULL;        buffer->tail = NULL;        buffer->length = 0;        buffer->trunk_num = 0;    }    else    {        buffer->head = chunk->next;        buffer->length -= chunk->length;        buffer->trunk_num--;    }    if (chunk->type == SW_CHUNK_DATA)    {        sw_free(chunk->store.ptr);    }    if (chunk->destroy)    {        chunk->destroy(chunk);    }    sw_free(chunk);}

swBuffer 缓冲区的销毁

int swBuffer_free(swBuffer *buffer){    volatile swBuffer_trunk *chunk = buffer->head;    void * *will_free_trunk;  //free the point    while (chunk != NULL)    {        if (chunk->type == SW_CHUNK_DATA)        {            sw_free(chunk->store.ptr);        }        will_free_trunk = (void *) chunk;        chunk = chunk->next;        sw_free(will_free_trunk);    }    sw_free(buffer);    return SW_OK;}

转载地址:http://pcgfl.baihongyu.com/

你可能感兴趣的文章
Linux Shell脚本系列之二
查看>>
设计模式--代理模式(Proxy Pattern)
查看>>
稀疏数组
查看>>
HTML5 标签 canvas
查看>>
react-router@4.0 使用方法和源码分析
查看>>
Flutter简介
查看>>
组织级敏捷转型的四个阶段
查看>>
「数据游戏」:使用 LSTM 模型预测三天后单股收盘价
查看>>
vuex持久化插件-解决浏览器刷新数据消失问题
查看>>
Vue-cli3 项目在安卓低版本系统和 IE 上白屏问题解决
查看>>
Mysql 慢查询优化实践
查看>>
并发-7-同步容器和ConcurrentHashMap
查看>>
小程序白屏问题和内存研究
查看>>
决战燕京城-01 执剑的少年(一)
查看>>
React安装:
查看>>
一次搞定js中的this指向
查看>>
从0开始搭建微信小程序(前后端)的全过程
查看>>
BBSSDK 产品分析
查看>>
Python入门教程:Day11-文件和异常
查看>>
用 Linux Shell 脚本来监控磁盘使用情况并发送邮件
查看>>