Sword nginx slab源码解析三(页分配)

static ngx_slab_page_t* ngx_slab_alloc_pages(ngx_slab_pool_t* pool, ngx_uint_t pages)
{
    ngx_slab_page_t  *page, *p;

    for (page = pool->free.next; page != &pool->free; page = page->next) 
    {

        if (page->slab >= pages) 
        {
            // 当前剩余页数 大于 需求页数

            if (page->slab > pages) 
            {
                /*
                设计说明:
                    page->slab 记录可用的页数
                    pages 需要申请的页数

                    那么被申请的页数即page[0] page[1] page[pages - 1]
                    剩下的空闲页是 page[pages]

                 备注:
                    不要把page看成数组,应该把page看成指针,page[pages] 即 page + pages
                    page 不等于 pool->pages
                */
                page[page->slab - 1].prev = (uintptr_t) &page[pages];

                // 更新新free页信息
                page[pages].slab = page->slab - pages;
                page[pages].next = page->next;
                page[pages].prev = page->prev;

                // 将已使用页从空闲链表上摘除
                p = (ngx_slab_page_t *) page->prev;
                // 空闲链表头指向下一个空闲页
                p->next = &page[pages];
                page->next->prev = (uintptr_t) &page[pages];

            } 
            else 
            {
                // 所有的空闲页恰好被用完

                p = (ngx_slab_page_t *) page->prev;
                p->next = page->next;
                page->next->prev = page->prev;
            }

            // 更新使用页节点信息

            // 记录当前页管理了多少页
            page->slab = pages | NGX_SLAB_PAGE_START;
            page->next = NULL;
            // 标记页的类型
            page->prev = NGX_SLAB_PAGE;

            // 更新空闲页数
            pool->pfree -= pages;

            if (--pages == 0) 
            {
                return page;
            }

            for (p = page + 1; pages; pages--) 
            {
                // 更新分配每一页的页信息
                p->slab = NGX_SLAB_PAGE_BUSY;
                p->next = NULL;
                p->prev = NGX_SLAB_PAGE;
                p++;
            }

            return page;
        }
    }

    if (pool->log_nomem) {
        ngx_slab_error(pool, NGX_LOG_CRIT,
                       "ngx_slab_alloc() failed: no memory");
    }

    return NULL;
}

 

posted on 2022-07-23 12:30  寒魔影  阅读(39)  评论(0编辑  收藏  举报

导航