函数指针初始化为null_swoole内存池分析(内存池初始化)

e6e4c2c815e5ca429c1d2c1e230feb8b.png

内存池的作用:

  1. 减少应用程序使用和释放的内存块过多并且过于频繁导致的内存分配成本过高。
  2. 频繁分配内存容易导致内存泄漏和内存碎片。
  3. 由内存池统一分配内存,提高内存分配性能。

swoole里的三个有关内存的结构体:

// swMemoryGlobal管理所有分配的内存page,是一个单链表。
typedef struct _swMemoryGlobal
{
    uint8_t shared;     // 是否进程间共享,shared = 1时,底层内存分配使用mmap生成一块共享内存区。
    uint32_t pagesize; // 每个内存页大小,为2*1024*1024
    swLock lock;       // 互斥锁
    swMemoryGlobal_page *root_page;    // 指向第一个swMemoryGlobal_page指针
    swMemoryGlobal_page *current_page; // 指向当前swMemoryGlobal_page指针
    uint32_t current_offset;
} swMemoryGlobal;
// 每个内存页的结构体
typedef struct _swMemoryGlobal_page
{
    struct _swMemoryGlobal_page *next; // 指向下一个内存页结构体
    char memory[0];  // 柔性数组,记录申请内存后的内存地址
} swMemoryGlobal_page;
// 内存池
typedef struct _swMemoryPool
{
    void *object; // swMemoryGlobal_page的memory
    void* (*alloc)(struct _swMemoryPool *pool, uint32_t size); // 分配内存的函数指针
    void (*free)(struct _swMemoryPool *pool, void *ptr); // 释放内存的函数指针
    void (*destroy)(struct _swMemoryPool *pool); // 销毁内存的函数指针
} swMemoryPool;

// swoole的内存分配就是在swMemoryPool进行的。
void swoole_init(void) {
  // 省略
    //init global shared memory
    // SW_GLOBAL_MEMORY_PAGESIZE = 2 * 1024 * 1024,每个内存页大小
    // shared = 1,这次创建的是共享内存
    SwooleG.memory_pool = swMemoryGlobal_new(SW_GLOBAL_MEMORY_PAGESIZE, 1);
    if (SwooleG.memory_pool == NULL)
    {
        printf("[Core] Fatal Error: global memory allocation failure");
        exit(1);
    }
  // 省略
}
swMemoryPool* swMemoryGlobal_new(uint32_t pagesize, uint8_t shared)
{
    // 全局内存管理器
    swMemoryGlobal gm, *gm_ptr;
    // pagesize不能大于2 * 1024 * 1024
    assert(pagesize >= SW_MIN_PAGE_SIZE);
    // 初始化全局内存管理器 gm
    bzero(&gm, sizeof(swMemoryGlobal));

    gm.shared = shared;  // 标记该内存为共享内存
    gm.pagesize = pagesize; // 标记该内存页大小
    swMemoryGlobal_page *page = swMemoryGlobal_new_page(&gm);
    if (page == NULL)
    {
        return NULL;
    }
    if (swMutex_create(&gm.lock, shared) < 0)
    {
        return NULL;
    }

    gm.root_page = page;  // 第一个swMemoryGlobal_page指针
   
    // 该全局内存管理器目前管理的内存空闲空间
    gm_ptr = (swMemoryGlobal *) page->memory;
    // 由于swMemoryGlobal的信息需要保存到page->memory中,gm.current_offset内存空间偏移需要
    // 加上这一部分,避免内存分配出现问题。
    gm.current_offset += sizeof(swMemoryGlobal);
   
    // 由于swMemoryPool内存池信息也要保存到page->memory中,gm.current_offset内存空间偏移需要
    // 加上这一部分,避免内存分配出现问题。
    swMemoryPool *allocator = (swMemoryPool *) (page->memory + gm.current_offset);
    gm.current_offset += sizeof(swMemoryPool);
    // 这里其实已经做了将swMemoryPool内存池信息也要保存到page->memory的步骤
    allocator->object = gm_ptr;  // 内存池具体管理的内存块
    allocator->alloc = swMemoryGlobal_alloc;  // 分配内存的函数
    allocator->destroy = swMemoryGlobal_destroy;  // 销毁内存的函数指针
    allocator->free = swMemoryGlobal_free;  // 释放内存的函数指针
    
    // 这里将全局内存管理器信息保存保存在gm_ptr指向的内存空间,也就是page->memory
    // 这就是gm.current_offset += sizeof(swMemoryGlobal)这步骤的原因
    memcpy(gm_ptr, &gm, sizeof(gm));
    return allocator;
}
static swMemoryGlobal_page* swMemoryGlobal_new_page(swMemoryGlobal *gm)
{
    // sw_shm_malloc用mmap创建共享内存
    // mmap该函数可以在unix网络编程卷2进程间通信找到详细说明
    // sw_malloc 也就是malloc
    swMemoryGlobal_page *page = (swMemoryGlobal_page *)((gm->shared == 1) ? sw_shm_malloc(gm->pagesize) : sw_malloc(gm->pagesize));
    if (page == NULL)
    {
        return NULL;
    }
    // 由于内存池的page可能不够,因此需要分配多次的page
    // 上一部分说道,swMemoryGlobal_page 是单链表
    bzero(page, gm->pagesize);
    page->next = NULL;
    
    if (gm->current_page != NULL)
    {
        gm->current_page->next = page;
    }

    gm->current_page = page;
    gm->current_offset = 0;

    return page;
}
void* sw_shm_malloc(size_t size)
{
    // 内存对齐
    size = SW_MEM_ALIGNED_SIZE(size);
    // 共享内存结构体
    swShareMemory object;
    void *mem;
    // 由于mmap分配的共享内存的信息也需要记录在分配的内存空间中,因此实际分配的内存大小
    // 为 size += sizeof(swShareMemory)
    size += sizeof(swShareMemory);
    mem = swShareMemory_mmap_create(&object, size, NULL);
    if (mem == NULL)
    {
        return NULL;
    }
    else
    {
       // mmap分配的共享内存的信息也需要记录在分配的内存空间中
        memcpy(mem, &object, sizeof(swShareMemory));
       // 只返回空闲的内存空间
        return (char *) mem + sizeof(swShareMemory);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值