程序员开发实例大全宝库

网站首页 > 编程文章 正文

Nginx共享内存管理之Slab(nginx 80 443共存)

zazugpt 2024-09-02 04:21:57 编程文章 23 ℃ 0 评论

之前我们学习到Nginx的worker进程之间通过共享内存进行通信。

Nginx在解析完配置文件,把即将使用的共享内存全部以链表的形式组织在全局变量cf->cycle->shared_memory,再进行实际的内存分配。

我们也知道了共享内存上 可以使用 红黑树、链表这样的数据结构。

但这些数据结构都是由一个一个的节点组成的,每个节点都需要内存去存放。

那怎么把一整块的共享内存 分配成小块给这些节点使用的呢?


Nginx使用了Slab具体是怎么管理共享内存的?

其实Nginx 的slab机制与Linux的slab机制基本原理是一致的,当然Linux 的slab机制肯定要更加复杂。

Slab会把整个共享内存分为多个页。假设每个页为4K,会把这4K切分成多个slot,如:32byte的slot,64byte的slot,128byte的slot,这些slot是成倍的方式增长的。也就是时候一页里会有多个slot。

那么要存储34字节的内容也会占用64字节,可以看出这种存储是有内存空间浪费的,但是对内存性能的提升是显著的。 这种内存分配方式叫最佳适应算法(best fit )关于内存分配算法 还有 首次适应算法(first Fit)、循环首次适用算法(next fit )、最坏适应算法(worst fit)以后有机会我们一起学习操作系统的时候 再系统学习这块的知识。

整体结构如图


这种Bestfit 有如下特点:

  • 适合小对象
  • 避免碎片
  • 避免重复初始化


我们一起来看下 slab 相关结构体 文件名:ngx_slab.h

typedef struct ngx_slab_page_s  ngx_slab_page_t;
// 用于管理内存页。
struct ngx_slab_page_s {
    uintptr_t         slab;
    ngx_slab_page_t  *next;
    uintptr_t         prev;
};
//用于统计信息。
typedef struct {
    ngx_uint_t        total; 
    ngx_uint_t        used;
    ngx_uint_t        reqs;
    ngx_uint_t        fails;
} ngx_slab_stat_t;

typedef struct {
    ngx_shmtx_sh_t    lock;
    size_t            min_size;  // 可分配的最小内存
    size_t            min_shift; // 最小内存对应的偏移值 (如果是3 则代表 min_size是 2^3)
    ngx_slab_page_t  *pages;    // 指向第一页的管理结构
    ngx_slab_page_t  *last;     // 指向最后一页的管理结构
    ngx_slab_page_t   free;     // 用于管理空闲页面
    ngx_slab_stat_t  *stats;    // 每种规格内存的统计信息
    ngx_uint_t        pfree;    // 空闲页数
    void             *data;
    void             *addr;
} ngx_slab_pool_t;


还提供了一组API来操作 如:

// 共享内存初始化,pool指向某个共享内存的首地址。
void ngx_slab_init(ngx_slab_pool_t *pool);
// 从pool 指向的共享内存快中申请大小 是size的内存。
void *ngx_slab_alloc(ngx_slab_pool_t *pool, size_t size);
// 释放pool 分配的某个内存。
void ngx_slab_free(ngx_slab_pool_t *pool, void *p);

ngx_slab_pool_t: 是共享内存管理的主要就靠这家伙了,处于共享内存的头部,我们可以从这个结构体里分配或释放共享内存里的内存。

ngx_slab_page_t: 管理内存页,用在next字段。有9种大小规格:8Byte,16Byte,32Byte,64Byte,128Byte,256Byte,512Byte,1024Byte,2048Byte

ngx_slab_stat_t: 用于统计每种规格page的信息。所以也有9种。

整体结构如下图:




我们可以通过slab_stat模块统计到每个slot共分配数,使用数,请求数,失败数。这就方便我们查看共享内存的使用情况。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表