Nginx系列二 slab分配器

nginx的slab分配器主要和共享内存(nginx自己实现的共享内存 采用mmap或者shm实现)一起使用,Nginx在解析完配置文件,把即将使用的共享内存全部以list链表的形式,对共享内存进行管理和划分。在nginx_cycle.c中

static ngx_int_t
ngx_init_zone_pool(ngx_cycle_t *cycle, ngx_shm_zone_t *zn)
{
    u_char           *file;
    ngx_slab_pool_t  *sp;

    sp = (ngx_slab_pool_t *) zn->shm.addr;

    if (zn->shm.exists) {

        if (sp == sp->addr) {
            return NGX_OK;
        }

        ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
                      "shared zone \"%V\" has no equal addresses: %p vs %p",
                      &zn->shm.name, sp->addr, sp);
        return NGX_ERROR;
    }

    sp->end = zn->shm.addr + zn->shm.size;
    sp->min_shift = 3;
    sp->addr = zn->shm.addr;

.......

   ngx_slab_init(sp);//在共享内存建立完成之后开始初始化 slab分配器

可以看到共享内存的开始部分用来存储ngx_slab_pool_t。

slab对于内存的管理主要有两个方面:一个是page的管理(包括静态对齐和动态分配),另一个是对小于page的slot 小内存的管理,slot内存段的管理是琐碎而频繁。

slab中常变量的表述如下:

变量名                                值                   描述

ngx_pagesize                   4096           系统页大小

ngx_pagesize_shift            12
         对应上项  4096=1<<12

pool->min_shirt                   3               固定值

pool->min_size                     8               最小分配8个字节

内存对齐能够减少不必要的碎片管理,另外内存对齐对内存访问的性能也有影响。参见这里.

整个slab管理器的定义如下

typedef struct ngx_slab_page_s  ngx_slab_page_t;

struct ngx_slab_page_s {
    uintptr_t         slab;  //32位表示page内128个字节的使用
    ngx_slab_page_t  *next;  下一个page
    uintptr_t         prev;
};

typedef struct {
    ngx_shmtx_sh_t    lock;

    size_t            min_size;
    size_t            min_shift;

    ngx_slab_page_t  *pages;
    ngx_slab_page_t   free;

    u_char           *start;
    u_char           *end;

    ngx_shmtx_t       mutex;

    u_char           *log_ctx;
    u_char            zero;

    unsigned          log_nomem:1;

    void             *data;
    void             *addr;
} ngx_slab_pool_t;

第一个问题:如何根据管理结构page获得对应的内存页的起始地址P呢?计算方法如下

 p = (page - pool->pages) << ngx_pagesize_shift;
            p += (uintptr_t) pool->start;

第二个问题,页面对齐可以提高内存的访问速度,slab是如何做到页面对齐的呢?  代码如下  实际上浪费了最后一个不满的page,在ngx_slab.c中

 m = pages - (pool->end - pool->start) / ngx_pagesize;
    if (m > 0) {
        pages -= m;
        pool->pages->slab = pages;
    }

动态页面的管理相对简单,既然所有闲置page都在链表上直接移除(分配时)就可以,  回收page的时候在头插到链表中,这里记住是头插。

业内slot的管理相对琐碎,不过slab的威力就在对琐碎频繁的小内存管理的能力。业内slot的管理,首先slab把slot划分为8,16,32,64,128,256,512,1024,2048,9条链表在ngx_slab_init()中:

    slots = (ngx_slab_page_t *) p;   //取得页首地址,实际上就是存放的page的管理struct
    n = ngx_pagesize_shift - pool->min_shift;  //12-3=9

    for (i = 0; i < n; i++) {
        slots[i].slab = 0;
        slots[i].next = &slots[i];
        slots[i].prev = 0;
    }

忘了说了,但超过2048个字节的申请,直接转向page的申请和管理不再由slot负责。

参考资料:

《深入剖析Nginx》高凯群

Nginx系列二 slab分配器

时间: 2024-08-25 00:42:30

Nginx系列二 slab分配器的相关文章

Nginx系列教程(二)| 一文带你读懂Nginx的正向与反向代理

作者:JackTian 微信公众号:杰哥的IT之旅(ID:Jake_Internet) LAMP 系列导读 01. LAMP 系列教程(一)| 详解 Linux 环境下部署 HTTPD 服务 02. LAMP 系列教程(二)| 如何在 Linux 环境下部署 AWStats 分析系统来监控 Web 站点? 03. LAMP 系列教程(三)| 一文读懂 HTTPD 服务的访问控制 04. LAMP 系列教程(四)| MySQL 数据库系统(一) 05. LAMP 系列教程(五)| MySQL 数据

[Linux内存]slab分配器学习笔记(二)--slab着色

slab着色原理 slab着的原理,cpu cache 一,slab着色原理 slab分配器中用到很多的缓存,每个缓存中又包含了很多slab,每个slab中有很多对象,每个slab的头部用于管理该slab中的对象(比如哪些对象已经使用,哪些对象还没有使用等),在slab的每个对象的开始和结束处都有一个特定分区填充特定的数据,这样后面如果这些数据和预先填充的不符合那么就可以证明该内存区被错误修改过,缓存的各个slab成员会指定不同的偏移量,以便将其定位到不同的缓存行中.在分配和释放slab时候,将

把握linux内核设计(十二):内存管理之slab分配器

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途] 上一节最后说到对于小内存区的请求,如果采用伙伴系统来进行分配,则会在页内产生很多空闲空间无法使用,因此产生slab分配器来处理对小内存区(几十或几百字节)的请求.Linux中引入Slab的主要目的是为了减少对伙伴算法的调用次数. 内核经常反复使用某一内存区.例如,只要内核创建一个新的进程,就要为该进程相关的数据结构(task_struct.打开文件对象等)分配内存区.当进程结

Nginx系列三 内存池的设计

Nginx的高性能的是用非常多细节来保证,epoll下的多路io异步通知.阶段细分化的异步事件驱动,那么在内存管理这一块也是用了非常大心血.上一篇我们讲到了slab分配器,我们能够能够看到那是对共享内存的管理的优化.Nginx在进程内也实现了自己的内存池,目的在于降低内存碎片,降低向操作系统的申请次数,减低模块开发难度.Nginx实现的内存池实际上非常easy: Nginx内存池的管理是分大内存和小内存的,详细说来.Nginx在向系统初始化内存池后,当我们调用ngx_palloc申请小内存后,再

[Linux内存]linux内存学习(六)——slab分配器

Linux Slab分配器(一)--概述 Linux Slab分配器(二)--初始化 Linux Slab分配器(三)--创建缓存 Linux Slab分配器(四)--分配对象 Linux Slab分配器(五)--释放对象 Linux Slab分配器(七)--销毁缓存

Nginx系列-1.Linux下安装Nginx

Nginx系列-1.Linux下安装Nginx 目录 - Nginx系列 Nginx系列-1.Linux下安装Nginx Nginx系列-2.配置LNMP(Linux.Nginx.MySQL.PHP)架构 Nginx系列-3.配置Nginx虚拟主机 Nginx系列-4.Nginx日志配置及日志切割 Nginx系列-5.配置Nginx的防盗链 Nginx系列-6.配置Nginx的HTTPS Nginx系列-7.配置Nginx使用uwsgi支持web.py框架 Nginx系列-8.配置Nginx+A

Nginx系列-5.配置Nginx的防盗链

Nginx系列-5.配置Nginx的防盗链 目录 - Nginx系列 Nginx系列-1.Linux下安装Nginx Nginx系列-2.配置LNMP(Linux.Nginx.MySQL.PHP)架构 Nginx系列-3.配置Nginx虚拟主机 Nginx系列-4.Nginx日志配置及日志切割 Nginx系列-5.配置Nginx的防盗链 Nginx系列-6.配置Nginx的HTTPS Nginx系列-7.配置Nginx使用uwsgi支持web.py框架 Nginx系列-8.配置Nginx+Apa

Nginx系列-2.配置LNMP(Linux、Nginx、MySQL、PHP)架构

Nginx系列-2.配置LNMP(Linux.Nginx.MySQL.PHP)架构 目录 - Nginx系列 Nginx系列-1.Linux下安装Nginx Nginx系列-2.配置LNMP(Linux.Nginx.MySQL.PHP)架构 Nginx系列-3.配置Nginx虚拟主机 Nginx系列-4.Nginx日志配置及日志切割 Nginx系列-5.配置Nginx的防盗链 Nginx系列-6.配置Nginx的HTTPS Nginx系列-7.配置Nginx使用uwsgi支持web.py框架 N

Nginx系列-6.配置Nginx的HTTPS

Nginx系列-6.配置Nginx的HTTPS 目录 - Nginx系列 Nginx系列-1.Linux下安装Nginx Nginx系列-2.配置LNMP(Linux.Nginx.MySQL.PHP)架构 Nginx系列-3.配置Nginx虚拟主机 Nginx系列-4.Nginx日志配置及日志切割 Nginx系列-5.配置Nginx的防盗链 Nginx系列-6.配置Nginx的HTTPS Nginx系列-7.配置Nginx使用uwsgi支持web.py框架 Nginx系列-8.配置Nginx+A