• Nginx:移植Nginx内存池 | 附测试用例


    ngx_mem_pool.h

    #pragma once
    #include<cstdlib>
    #include<memory>
    
    // 类型重命名
    using u_char = unsigned char;
    using ngx_uint_t = unsigned int;
    
    // 回调函数 
    typedef void (*ngx_pool_cleanup_pt)(void* data);
    struct ngx_pool_cleanup_s {
    	ngx_pool_cleanup_pt   handler;	// 定义了一个函数指针,保存清理操作的回调函数
    	void*				  data;		// 传递给回调函数的参数
    	ngx_pool_cleanup_s* next;		// 所有的cleanup操作都被串在一条链表上
    };
    
    // 大块内存头部信息
    using ngx_pool_large_t = struct ngx_pool_large_s;
    struct ngx_pool_large_s {
    	ngx_pool_large_s* next;		// 大块内存也被串在一条链表上
    	void* alloc;				// 保存大块内存地址的起始位置
    };
    
    // 分配小块内存的内存池头部信息
    using ngx_pool_t = struct ngx_pool_s;
    
    struct ngx_pool_data_t {
    	u_char* last;		// 可用小块内存的起始位置
    	u_char* end;		// 末尾位置
    	ngx_pool_t* next;	// 链表,连接下一个小块内存
    	ngx_uint_t failed;	// 记录了当前小块内存分配失败的次数
    };
    
    // 内存池头部信息和管理成员信息
    struct ngx_pool_s {
    	ngx_pool_data_t       d;		// 当前小块内存的使用情况
    	size_t                max;		// 小块内存和大块内存的分界线	
    	ngx_pool_t* current;			// 指向第一个可提供小块内存分配的小块内存池
    	ngx_pool_large_t* large;		// 指向大块内存的入口地址
    	ngx_pool_cleanup_s* cleanup;	// 指向所有预置的清理操作(回调函数)的入口
    };
    
    // 把数值d调整成临近a的倍数
    #define ngx_align(d, a)     (((d) + (a - 1)) & ~(a - 1))
    // 把指针p调整成a临近的倍数
    #define ngx_align_ptr(p, a)                                                   \
        (u_char *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1))
    // 特定平台 小块内存分配考虑字节对齐时的单位
    #define NGX_ALIGNMENT   sizeof(unsigned long)    /* platform word */
    // 将指定内存置为0
    #define ngx_memzero(buf, n)       (void) memset(buf, 0, n)
    // free()
    #define ngx_free free
    
    /*
    移植Nginx内存池的代码
    */
    
    /*
     * NGX_MAX_ALLOC_FROM_POOL should be (ngx_pagesize - 1), i.e. 4095 on x86.
     * On Windows NT it decreases a number of locked pages in a kernel.
     */
    // 默认一个物理页面的大小4K
    const int ngx_pagesize = 4096;
    // 小块内存池可分配的最大空间
    const int NGX_MAX_ALLOC_FROM_POOL = ngx_pagesize - 1;
    // 默认内存池的大小
    const int NGX_DEFAULT_POOL_SIZE = 16 * 1024;
    // 内存池按照16个字节对齐
    const int NGX_POOL_ALIGNMENT = 16;
    
    // ngx小块内存池最小的size调整成NGX_POOL_ALIGNMENT邻近的倍数
    const int NGX_MIN_POOL_SIZE = ngx_align((sizeof(ngx_pool_t) + 2 * sizeof(ngx_pool_large_t)), NGX_POOL_ALIGNMENT);
    
    class ngx_mem_pool
    {
    public:
    
    	// 创建指定size大小的内存池(小块内存不超过一个页面4095)
    	void* ngx_create_pool(size_t size);
    
    	// 考虑内存对齐,从内存池申请size大小
    	void* ngx_palloc(size_t size);
    
    	// 和上面一样,但不考虑内存对齐
    	void* ngx_pnalloc(size_t size);
    
    	// 调用的是ngx_palloc(),但会初始化为0
    	void* ngx_pcalloc(size_t size);
    
    	// 释放大块内存
    	void ngx_pfree(void* p);
    
    	// 内存重置函数
    	void ngx_reset_pool();
    
    	// 内存池销毁函数
    	void ngx_destroy_pool();
    
    	// 添加回调清理操作函数
    	ngx_pool_cleanup_s* ngx_pool_cleanup_add(size_t size);
    
    private:
    	ngx_pool_s* pool;
    
    	// 小块内存分配
    	void* ngx_palloc_small(size_t size, ngx_uint_t align);
    	// 分配新的小块内存池
    	void* ngx_palloc_block(size_t size);
    	// 大块内存分配
    	void* ngx_palloc_large(size_t size);
    
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113

    ngx_mem_pool.cpp

    创建内存池和销毁内存池可以放在内存池的构造函数和析构函数中,这里没有放,所以在创建过程中把地址赋给内存池成员pool。

    #include "ngx_mem_pool.h"
    
    // 创建内存池
    void* ngx_mem_pool::ngx_create_pool(size_t size)
    {
        ngx_pool_s* p;
    
        p = (ngx_pool_s*)malloc(size);
        if (p == nullptr) {
            return nullptr;
        }
    
        p->d.last = (u_char*)p + sizeof(ngx_pool_s);
        p->d.end = (u_char*)p + size;
        p->d.next = nullptr;
        p->d.failed = 0;
    
        size = size - sizeof(ngx_pool_s);
        p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;
    
        p->current = p;
    
        p->large = nullptr;
        p->cleanup = nullptr;
    
        // 赋值给我的成员变量
        pool = p;
    
        return p;
    }
    
    // 考虑内存对齐,从内存池申请size大小
    void* ngx_mem_pool::ngx_palloc(size_t size)
    {
        if (size <= pool->max) {
            return ngx_palloc_small( size, 1);
        }
        return ngx_palloc_large(size);
    }
    
    // 和上面一样,但不考虑内存对齐
    void* ngx_mem_pool::ngx_pnalloc(size_t size)
    {
        if (size <= pool->max) {
            return ngx_palloc_small(size, 0);
        }
    
        return ngx_palloc_large(size);
    }
    
    // 调用的是ngx_palloc(),但会初始化为0
    void* ngx_mem_pool::ngx_pcalloc(size_t size)
    {
        void* p;
    
        p = ngx_palloc(size);
        if (p) {
            ngx_memzero(p, size);
        }
    
        return p;
    }
    
    // 小块内存分配
    void* ngx_mem_pool::ngx_palloc_small(size_t size, ngx_uint_t align)
    {
        u_char* m;
        ngx_pool_t* p;
        p = pool->current;
    
        do {
            m = p->d.last;
    
            if (align) {
                m = ngx_align_ptr(m, NGX_ALIGNMENT);
            }
    
            if ((size_t)(p->d.end - m) >= size) {
                p->d.last = m + size;
    
                return m;
            }
    
            p = p->d.next;
        } while (p);
    
        return ngx_palloc_block(size);
    }
    // 分配新的小块内存池
    void* ngx_mem_pool::ngx_palloc_block(size_t size)
    {
        u_char* m;
        size_t       psize;
        ngx_pool_t* p, * new_pool;
    
        psize = (size_t)(pool->d.end - (u_char*)pool);
    
        m = (u_char*)malloc(psize);
        if (m == nullptr) {
            return nullptr;
        }
    
        new_pool = (ngx_pool_s*)m;
    
        new_pool->d.end = m + psize;
        new_pool->d.next = nullptr;
        new_pool->d.failed = 0;
    
        m += sizeof(ngx_pool_data_t);
        m = ngx_align_ptr(m, NGX_ALIGNMENT);
        new_pool->d.last = m + size;
    
        for (p = pool->current; p->d.next; p = p->d.next) {
            if (p->d.failed++ > 4) {
                pool->current = p->d.next;
            }
        }
    
        p->d.next = new_pool;
    
        return m;
    }
    
    // 大块内存分配
    void* ngx_mem_pool::ngx_palloc_large(size_t size)
    {
        void* p;
        ngx_uint_t         n;
        ngx_pool_large_t* large;
    
        p = malloc(size);
        if (p == nullptr) {
            return nullptr;
        }
    
        n = 0;
        for (large = pool->large; large; large = large->next) {
            if (large->alloc == nullptr) {
                large->alloc = p;
                return p;
            }
    
            if (n++ > 3) {
                break;
            }
        }
    
        large = (ngx_pool_large_t*)ngx_palloc_small( sizeof(ngx_pool_large_s), 1);
        if (large == nullptr) {
            ngx_free(p);
            return nullptr;
        }
    
        large->alloc = p;
        large->next = pool->large;
        pool->large = large;
    
        return p;
    }
    
    // 释放大块内存
    void ngx_mem_pool::ngx_pfree(void* p)
    {
        ngx_pool_large_t* l;
    
        for (l = pool->large; l; l = l->next) {
            if (p == l->alloc) {
                ngx_free(l->alloc);
                l->alloc = nullptr;
    
                return;
            }
        }
    }
    
    // 内存重置函数
    void ngx_mem_pool::ngx_reset_pool()
    {
        ngx_pool_t* p;
        ngx_pool_large_t* l;
    
        // 大块内存的释放
        for (l = pool->large; l; l = l->next) {
            if (l->alloc) {
                ngx_free(l->alloc);
            }
        }
    
        // the first block
        p = pool;
        p->d.last = (u_char*)p + sizeof(ngx_pool_t);
        p->d.failed = 0;
    
        // remaining memory pool
        for (p = p->d.next; p; p = p->d.next) {
            p->d.last = (u_char*)p + sizeof(ngx_pool_data_t);
            p->d.failed = 0;
        }
    
        pool->current = pool;
        pool->large = nullptr;
    }
    
    // 内存池销毁函数
    void ngx_mem_pool::ngx_destroy_pool()
    {
        ngx_pool_t* p, * n;
        ngx_pool_large_t* l;
        ngx_pool_cleanup_s* c;
    
        for (c = pool->cleanup; c; c = c->next) {
            if (c->handler) {
                c->handler(c->data);
            }
        }
    
        for (l = pool->large; l; l = l->next) {
            if (l->alloc) {
                ngx_free(l->alloc);
            }
        }
    
        for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
            ngx_free(p);
    
            if (n == nullptr) {
                break;
            }
        }
    }
    
    // 添加回调清理操作函数
    ngx_pool_cleanup_s* ngx_mem_pool::ngx_pool_cleanup_add(size_t size)
    {
        ngx_pool_cleanup_s* c;
    
        c = (ngx_pool_cleanup_s*)ngx_palloc(sizeof(ngx_pool_cleanup_s));
        if (c == nullptr)
        {
            return nullptr;
        }
    
        if (size)
        {
            c->data = ngx_palloc(size);
            if (c->data == nullptr)
            {
                return nullptr;
            }
        }
        else 
        {
            c->data = nullptr;
        }
    
        c->handler = nullptr;
        c->next = pool->cleanup;
    
        pool->cleanup = c;
    
        return c;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262

    ngx_test_pool.cpp

    #define _CRT_SECURE_NO_WARNINGS
    #include "ngx_mem_pool.h"
    #include <iostream>
    #include<cstring>
    using namespace std;
    
    typedef struct Data stData;
    struct Data
    {
        char* ptr;
        FILE* pfile;
    };
    
    void func1(void* p1) // void (*)(void*)
    {
        char* p = (char*)p1;
        cout << "free ptr mem!" << endl;
        delete p;
    }
    void func2(void* pf1)
    {
        FILE* pf = (FILE*)pf1;
        cout << "close file!" << endl;
        fclose(pf);
    }
    
    int main(void)
    {
        ngx_mem_pool mempool;
        // 512 - sizeof(ngx_pool_t) - 4095   =>   max
        if (nullptr == mempool.ngx_create_pool(512))
        {
            cout << "ngx_create_pool fail..." << endl;
            return -1;
        }
    
        void* p1 = mempool.ngx_palloc(128); // 从小块内存池分配的
        if (nullptr == p1)
        {
            cout << "ngx_palloc 128 bytes fail..." << endl;
            return -1;
        }
    
        stData* p2 = (stData*)mempool.ngx_palloc(512); // 从大块内存池分配的
        if (nullptr == p2)
        {
            cout << "ngx_palloc 512 bytes fail..." << endl;
            return -1;
        }
        p2->ptr = (char*)malloc(12);
        strcpy(p2->ptr, "hello world");
        p2->pfile = fopen("data.txt", "w");
    
        ngx_pool_cleanup_s* c1 = mempool.ngx_pool_cleanup_add(sizeof(char*));
        c1->handler = func1;
        c1->data = p2->ptr;
    
        ngx_pool_cleanup_s* c2 = mempool.ngx_pool_cleanup_add(sizeof(FILE*));
        c2->handler = func2;
        c2->data = p2->pfile;
    
        mempool.ngx_destroy_pool(); // 1.调用所有的预置的清理函数 2.释放大块内存 3.释放小块内存池所有内存
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
  • 相关阅读:
    艾美捷Bio-Helix BluPAD双LED蓝白光照胶台丨舒适、方便
    算法通过村第十七关-贪心|青铜笔记|贪心也很简单呕
    ubuntu20.04运用startup application开机自启动python程序
    STM32基于HAL库的非DMA的轮询ADC单通道与多通道的采样
    【leetcode】1137. 第 N 个泰波那契数
    《乔布斯传》英文原著重点词汇笔记(八)【 chapter six 】
    CTFHUB ICS(2)
    大语言模型构建的主要四个阶段(各阶段使用的算法、数据、难点以及实践经验)
    C++设计模式-创建型设计模式:构建者(Builder)
    中秋月饼还没有恰到,先用css画一个月亮赏赏眼
  • 原文地址:https://blog.csdn.net/m0_56257585/article/details/125505934