So implementieren Sie den Nginx-Speicherpool

WBOY
Freigeben: 2023-05-17 13:26:27
nach vorne
1318 Leute haben es durchsucht

1. Einführung

Die neueste stabile Version nginx1.20.2.
Um Speicher effizient und schnell zuzuweisen und die Speicherfragmentierung zu reduzieren, implementiert Nginx eine eigene grundlegende Speicherpoolkomponente.
Hauptimplementierungsdateien ngx_palloc.h, ngx_palloc.cngx_palloc.h, ngx_palloc.c

二、数据结构

2.1 内存池主要结构

typedef struct {
    u_char               *last;
    u_char               *end;
    ngx_pool_t           *next;
    ngx_uint_t            failed;
} ngx_pool_data_t;

struct ngx_pool_s {
    ngx_pool_data_t       d;
    size_t                max;
    ngx_pool_t           *current;
    ngx_chain_t          *chain;
    ngx_pool_large_t     *large;
    ngx_pool_cleanup_t   *cleanup;
    ngx_log_t            *log;
};
Nach dem Login kopieren

内存池中第一个成员是一个结构体:
使用ngx_pool_data_t结构体来表示当前内存池信息。
last :下次开始分配的地址
end: 内存池的结束地址
next: 内存池链表,将多个内存池连接起来

max
整个内存池的最大大小

current
指向从当前内存池开始查找可用内存

chain
buffer使用的,这里不涉及

large
当需要的内存大于内存池最大大小时,需要通过malloc直接分配,然后形成链表进行组织

cleanup
清理工作的回调链表

log
日志句柄

2.2 大内存链

当需要分配的内存比内存池的最大大小都大时,内存池无法满足分配,所以直接从系统中分配,然后构成一个链表进行维护。

typedef struct ngx_pool_large_s  ngx_pool_large_t;

struct ngx_pool_large_s {
    ngx_pool_large_t     *next;
    void                 *alloc;
};
Nach dem Login kopieren

2.3 清理任务链

有一个回调任务的链表,当内存池销毁时,将依次遍历此链表,逐一回调handler进行清理工作。

typedef void (*ngx_pool_cleanup_pt)(void *data);

typedef struct ngx_pool_cleanup_s  ngx_pool_cleanup_t;

struct ngx_pool_cleanup_s {
    ngx_pool_cleanup_pt   handler;
    void                 *data;
    ngx_pool_cleanup_t   *next;
};
Nach dem Login kopieren

三、内存结构图

3.1 逻辑

So implementieren Sie den Nginx-Speicherpool

3.2 实际

So implementieren Sie den Nginx-Speicherpool

可以看出,很多节点都是从内存池中分配的,所以可以把精力都放在实际的数据上而不必在意其他细节上。

四、实现

4.1 创建内存池

/*
 * 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.
 */
#define NGX_MAX_ALLOC_FROM_POOL  (ngx_pagesize - 1)

#define NGX_DEFAULT_POOL_SIZE    (16 * 1024)
Nach dem Login kopieren
ngx_pool_t *
ngx_create_pool(size_t size, ngx_log_t *log)
{
    ngx_pool_t  *p;

    p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log);
    if (p == NULL) {
        return NULL;
    }

    p->d.last = (u_char *) p + sizeof(ngx_pool_t);
    p->d.end = (u_char *) p + size;
    p->d.next = NULL;
    p->d.failed = 0;

    size = size - sizeof(ngx_pool_t);
    p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;

    p->current = p;
    p->chain = NULL;
    p->large = NULL;
    p->cleanup = NULL;
    p->log = log;

    return p;
}
Nach dem Login kopieren

从代码中可以看到,内存池最大不超过pagesize的大小

So implementieren Sie den Nginx-Speicherpool

4.2 从内存池中分配空间

分配函数分了内存对齐和内存不对齐,但这只控制了内存池中分配空间,不控制大内存分配。

(1)分配小空间

  • 内存对齐 ngx_palloc

  • 内存不对齐 ngx_pnalloc

void *
ngx_palloc(ngx_pool_t *pool, size_t size)
{
#if !(NGX_DEBUG_PALLOC)
    if (size <= pool->max) {
        return ngx_palloc_small(pool, size, 1);
    }
#endif

    return ngx_palloc_large(pool, size);
}
Nach dem Login kopieren

当需要分配的空间小于max时,将使用小内存分配方式(即从内存池中分配空间),而ngx_pnalloc和ngx_palloc相比只是调用ngx_palloc_small时的最后一个参数为0。

从pool->current指向的内存池开始遍历,寻找满足分配大小的空间,找到则返回首地址

static ngx_inline void *
ngx_palloc_small(ngx_pool_t *pool, 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(pool, size);
}
Nach dem Login kopieren

当现有内存池中都无法满足分配条件时,创建新的内存池

static void *
ngx_palloc_block(ngx_pool_t *pool, size_t size)
{
    u_char      *m;
    size_t       psize;
    ngx_pool_t  *p, *new;

    psize = (size_t) (pool->d.end - (u_char *) pool);

    m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log);
    if (m == NULL) {
        return NULL;
    }

    new = (ngx_pool_t *) m;

    new->d.end = m + psize;
    new->d.next = NULL;
    new->d.failed = 0;

    m += sizeof(ngx_pool_data_t);
    m = ngx_align_ptr(m, NGX_ALIGNMENT);
    new->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;

    return m;
}
Nach dem Login kopieren

其中,创建好新的内存池后,又做了一次遍历,将failed计数加一,当大于4时,将跳过此内存池,下次就不从它开始查找。
即认为超过4次你都不能满足分配,以后都不能满足分配,不再用你了,减少遍历个数,加快成功分配效率

(2)分配大空间

static void *
ngx_palloc_large(ngx_pool_t *pool, size_t size)
{
    void              *p;
    ngx_uint_t         n;
    ngx_pool_large_t  *large;

    p = ngx_alloc(size, pool->log);
    if (p == NULL) {
        return NULL;
    }

    n = 0;

    for (large = pool->large; large; large = large->next) {
        if (large->alloc == NULL) {
            large->alloc = p;
            return p;
        }

        if (n++ > 3) {
            break;
        }
    }

    large = ngx_palloc_small(pool, sizeof(ngx_pool_large_t), 1);
    if (large == NULL) {
        ngx_free(p);
        return NULL;
    }

    large->alloc = p;
    large->next = pool->large;
    pool->large = large;

    return p;
}
Nach dem Login kopieren

可以看出,为了避免分配空间,遍历large链查找可重用的节点,但是如果链表过大又可能太慢,所以只查找前三个,如果三个都没有找到,则直接分配(而且节点也是从内存池中分配的,所以后续清理时,不需要管节点,只需要释放申请的大内存本身)

内存对齐

void *
ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment)
{
    void              *p;
    ngx_pool_large_t  *large;

    p = ngx_memalign(alignment, size, pool->log);
    if (p == NULL) {
        return NULL;
    }

    large = ngx_palloc_small(pool, sizeof(ngx_pool_large_t), 1);
    if (large == NULL) {
        ngx_free(p);
        return NULL;
    }

    large->alloc = p;
    large->next = pool->large;
    pool->large = large;

    return p;
}
Nach dem Login kopieren

4.3 注册清理任务

ngx_pool_cleanup_t *
ngx_pool_cleanup_add(ngx_pool_t *p, size_t size)
{
    ngx_pool_cleanup_t  *c;

    c = ngx_palloc(p, sizeof(ngx_pool_cleanup_t));
    if (c == NULL) {
        return NULL;
    }

    if (size) {
        c->data = ngx_palloc(p, size);
        if (c->data == NULL) {
            return NULL;
        }

    } else {
        c->data = NULL;
    }

    c->handler = NULL;
    c->next = p->cleanup;

    p->cleanup = c;

    ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, p->log, 0, "add cleanup: %p", c);

    return c;
}
Nach dem Login kopieren

可以看出,这里只是分配了一个节点,并没有设置handler以及data数据,所以还得看具体的调用方进行设置,因为这里返回了分配的节点。

比如在函数ngx_create_temp_file

ngx_int_t
ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool,
    ngx_uint_t persistent, ngx_uint_t clean, ngx_uint_t access)
{
    ...

    cln = ngx_pool_cleanup_add(pool, sizeof(ngx_pool_cleanup_file_t));
    if (cln == NULL) {
        return NGX_ERROR;
    }

       ...
        file->fd = ngx_open_tempfile(file->name.data, persistent, access);
				...
        if (file->fd != NGX_INVALID_FILE) {

            cln->handler = clean ? ngx_pool_delete_file : ngx_pool_cleanup_file;
            clnf = cln->data;

            clnf->fd = file->fd;
            clnf->name = file->name.data;
            clnf->log = pool->log;

            return NGX_OK;
        }
			...
}
Nach dem Login kopieren

生成临时文件,将fd以及文件名注册到清理任务中,后续文件不使用了则不需要特殊处理,内存内存池释放时将统一清理。

4.4 重置内存池

  • 释放大内存

  • 重置内存中last

  • 重置failed计数

void
ngx_reset_pool(ngx_pool_t *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);
        }
    }

    for (p = pool; p; p = p->d.next) {
        p->d.last = (u_char *) p + sizeof(ngx_pool_t);
        p->d.failed = 0;
    }

    pool->current = pool;
    pool->chain = NULL;
    pool->large = NULL;
}
Nach dem Login kopieren

这里有个现象:
在内存池中空间不足时,将调用ngx_palloc_block创建一个新的内存池,而last指向的是m += sizeof(ngx_pool_data_t);, 因此当前新分配的内存池将比第一个内存池可用大小多了(max,current,chain,large,cleanup,log)这几个字段大小(可能没有那么多,因为要对齐,可能对齐后就完全一样了),而现在重置时,p->d.last = (u_char *) p + sizeof(ngx_pool_t);

II. Datenstruktur

2.1 Hauptstruktur des Speicherpools
    void
    ngx_destroy_pool(ngx_pool_t *pool)
    {
        ngx_pool_t          *p, *n;
        ngx_pool_large_t    *l;
        ngx_pool_cleanup_t  *c;
    
        for (c = pool->cleanup; c; c = c->next) {
            if (c->handler) {
                ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
                               "run cleanup: %p", c);
                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 == NULL) {
                break;
            }
        }
    }
    Nach dem Login kopieren
    Nach dem Login kopieren
  • Das erste Mitglied des Speicherpools ist eine Struktur:

    Verwenden Sie die Der Strukturkörper ngx_pool_data_t stellt die aktuellen Speicherpoolinformationen dar.

    last: die Adresse, die beim nächsten Mal zugewiesen werden soll
  • end: die Endadresse des Speicherpools
  • next: eine verknüpfte Liste des Speicherpools, die mehrere Speicherpools verbindet

    max
  • Die maximale Größe des gesamten Speicherpools
  • aktuelle

    Punkte Beginnen Sie mit der Suche nach verfügbarem Speicher aus dem aktuellen Speicherpool. 🎜🎜Kette🎜Puffer wird verwendet, was hier nicht in Frage kommt🎜🎜groß🎜Wenn der erforderliche Speicher größer als die maximale Größe des Speicherpools ist, muss er direkt über malloc zugewiesen werden und dann in einer verknüpften Liste organisiert , kann der Speicherpool die Zuweisung nicht erfüllen, daher wird er direkt vom System zugewiesen und bildet dann eine verknüpfte Liste zur Wartung. 🎜
    ngx_int_t
    ngx_pfree(ngx_pool_t *pool, void *p)
    {
        ngx_pool_large_t  *l;
    
        for (l = pool->large; l; l = l->next) {
            if (p == l->alloc) {
                ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
                               "free: %p", l->alloc);
                ngx_free(l->alloc);
                l->alloc = NULL;
    
                return NGX_OK;
            }
        }
    
        return NGX_DECLINED;
    }
    Nach dem Login kopieren
    Nach dem Login kopieren
    🎜2.3 Bereinigungsaufgabenkette🎜🎜Es gibt eine verknüpfte Liste von Rückrufaufgaben. Wenn der Speicherpool zerstört wird, wird diese verknüpfte Liste der Reihe nach durchlaufen und die Handler werden nacheinander zurückgerufen, um Reinigungsarbeiten durchzuführen. 🎜
    void *
    ngx_pcalloc(ngx_pool_t *pool, size_t size)
    {
        void *p;
    
        p = ngx_palloc(pool, size);
        if (p) {
            ngx_memzero(p, size);
        }
    
        return p;
    }
    Nach dem Login kopieren
    Nach dem Login kopieren
    🎜3. Speicherstrukturdiagramm🎜🎜3.1 Logik🎜🎜Was ist mit Nginx-Speicher? Pool-Implementierung🎜🎜3.2 Actual🎜🎜So implementieren Sie den Nginx-Speicherpool 🎜🎜Es ist ersichtlich, dass viele Knoten aus dem Speicherpool zugewiesen werden, sodass Sie sich auf die tatsächlichen Daten konzentrieren können, ohne sich um andere Details kümmern zu müssen. 🎜4. Implementierung /upload/article/ 000/887/227/168430118922665.png" alt="So implementieren Sie den Nginx-Speicherpool" />🎜🎜4.2 Speicherplatz aus dem Speicherpool zuweisen🎜🎜Die Zuordnungsfunktion ist in Speicherausrichtung und Speicherfehlausrichtung unterteilt. Es steuert jedoch nur den Speicherpool, der Speicherplatz zuweist, und steuert nicht die Zuweisung großer Speicher. 🎜🎜(1) Wenigen Speicherplatz zuweisen 🎜🎜🎜🎜Speicherausrichtung ngx_palloc🎜🎜🎜🎜Speicherfehlausrichtung ngx_pnalloc🎜🎜
void
ngx_pool_run_cleanup_file(ngx_pool_t *p, ngx_fd_t fd)
{
    ngx_pool_cleanup_t       *c;
    ngx_pool_cleanup_file_t  *cf;

    for (c = p->cleanup; c; c = c->next) {
        if (c->handler == ngx_pool_cleanup_file) {

            cf = c->data;

            if (cf->fd == fd) {
                c->handler(cf);
                c->handler = NULL;
                return;
            }
        }
    }
}
Nach dem Login kopieren
Nach dem Login kopieren
🎜Wenn zugewiesener Speicherplatz benötigt wird. Wann Wenn es kleiner als max ist, wird die kleine Speicherzuweisungsmethode (dh die Zuweisung von Speicherplatz aus dem Speicherpool) verwendet. Im Vergleich zu ngx_palloc hat ngx_pnalloc beim Aufruf von ngx_palloc_small nur den letzten Parameter 0. 🎜🎜Beginnen Sie mit dem Durchlaufen des Speicherpools, auf den pool->current zeigt, suchen Sie nach einem Speicherplatz, der der Zuordnungsgröße entspricht, und geben Sie, wenn er gefunden wird, die erste Adresse zurück. 🎜
void
ngx_pool_cleanup_file(void *data)
{
    ngx_pool_cleanup_file_t  *c = data;

    ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, c->log, 0, "file cleanup: fd:%d",
                   c->fd);

    if (ngx_close_file(c->fd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                      ngx_close_file_n " \"%s\" failed", c->name);
    }
}
Nach dem Login kopieren
Nach dem Login kopieren
🎜Wenn die Zuordnungsbedingungen im vorhandenen Speicherpool nicht erfüllt werden können, erstellen Sie ein neuer Speicherpool🎜
void
ngx_pool_delete_file(void *data)
{
    ngx_pool_cleanup_file_t  *c = data;

    ngx_err_t  err;

    ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, c->log, 0, "file cleanup: fd:%d %s",
                   c->fd, c->name);

    if (ngx_delete_file(c->name) == NGX_FILE_ERROR) {
        err = ngx_errno;

        if (err != NGX_ENOENT) {
            ngx_log_error(NGX_LOG_CRIT, c->log, err,
                          ngx_delete_file_n " \"%s\" failed", c->name);
        }
    }

    if (ngx_close_file(c->fd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                      ngx_close_file_n " \"%s\" failed", c->name);
    }
}
Nach dem Login kopieren
Nach dem Login kopieren
🎜Unter diesen wird nach dem Erstellen eines neuen Speicherpools ein weiterer Durchlauf durchgeführt, um die Anzahl der Fehler um eins zu erhöhen. Wenn er größer als 4 ist, wird dieser Speicherpool übersprungen und die Suche wird nicht von dort aus gestartet Nächstes Mal. 🎜Das heißt, es wird davon ausgegangen, dass Sie die Zuweisung nicht mehr als viermal erfüllen können und dass Sie die Zuweisung in Zukunft nicht mehr erfüllen können. Reduzieren Sie die Anzahl der Durchläufe und beschleunigen Sie die Effizienz erfolgreiche Zuweisung🎜🎜(2) Weisen Sie großen Speicherplatz zu🎜rrreee🎜Es ist ersichtlich, dass die verknüpfte Liste möglicherweise zu langsam ist, um dies zu vermeiden. Weisen Sie Speicherplatz zu und durchqueren Sie die große Kette, um wiederverwendbare Knoten zu finden. Daher werden nur die ersten drei durchsucht. Wenn keiner der drei gefunden wird, werden sie direkt zugewiesen (und die Knoten werden auch aus dem Speicherpool zugewiesen). Daher müssen Sie den Knoten bei der anschließenden Bereinigung nicht verwalten, sondern nur um den angewendeten großen Speicher selbst freizugeben)🎜🎜Speicherausrichtung🎜rrreee🎜4.3 Registrieren der Bereinigungsaufgabe🎜rrreee🎜Es ist ersichtlich, dass hier nur ein Knoten zugewiesen ist und kein Handler und keine Daten festgelegt sind, es hängt also von der ab spezifischer Aufrufer für Einstellungen, da hier der zugeordnete Knoten zurückgegeben wird. 🎜🎜Zum Beispiel generiert 🎜rrreee🎜 in der Funktion ngx_create_temp_file eine temporäre Datei, registriert den fd und den Dateinamen in der Bereinigungsaufgabe und es ist keine spezielle Verarbeitung erforderlich, wenn nachfolgende Dateien nicht verwendet werden Der Speicherpool wird vereinheitlicht, wenn er freigegeben wird. 🎜🎜4.4 Speicherpool zurücksetzen. Großer Speicher freigeben Wenn dies nicht ausreicht, wird ngx_palloc_block aufgerufen, um einen neuen Speicherpool zu erstellen, und zeigt zuletzt auf m += sizeof(ngx_pool_data_t);, also den aktuellen neu zugewiesenen Speicherpool wird größer sein als Die verfügbare Größe des ersten Speicherpools ist viel größer (maximal, aktuell, Kette, groß, Bereinigung, Protokoll) und die Größe dieser Felder (vielleicht nicht so groß, weil sie ausgerichtet werden müssen, vielleicht wird es so sein). genau das Gleiche nach der Ausrichtung), und jetzt wird es zurückgesetzt. Wenn p->d.last = (u_char *) p + sizeof(ngx_pool_t); die verfügbare Größe jedes Speicherpools gleich wird wieder. 🎜🎜4.5 Speicherpool zerstören🎜🎜🎜🎜Aufgabe zur Rückrufbereinigung🎜🎜🎜🎜Großen Speicher freigeben🎜🎜🎜🎜Speicherpool selbst freigeben🎜
void
ngx_destroy_pool(ngx_pool_t *pool)
{
    ngx_pool_t          *p, *n;
    ngx_pool_large_t    *l;
    ngx_pool_cleanup_t  *c;

    for (c = pool->cleanup; c; c = c->next) {
        if (c->handler) {
            ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
                           "run cleanup: %p", c);
            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 == NULL) {
            break;
        }
    }
}
Nach dem Login kopieren
Nach dem Login kopieren

4.6 大内存释放

通过遍历找到要释放的节点,将内存释放,并且将alloc设置成NULL,则有了节点重用的情况。

ngx_int_t
ngx_pfree(ngx_pool_t *pool, void *p)
{
    ngx_pool_large_t  *l;

    for (l = pool->large; l; l = l->next) {
        if (p == l->alloc) {
            ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
                           "free: %p", l->alloc);
            ngx_free(l->alloc);
            l->alloc = NULL;

            return NGX_OK;
        }
    }

    return NGX_DECLINED;
}
Nach dem Login kopieren
Nach dem Login kopieren

4.7 分配并清空数据

void *
ngx_pcalloc(ngx_pool_t *pool, size_t size)
{
    void *p;

    p = ngx_palloc(pool, size);
    if (p) {
        ngx_memzero(p, size);
    }

    return p;
}
Nach dem Login kopieren
Nach dem Login kopieren

正常分配的空间中都是垃圾数据,所以当前函数在分配空间后,将分配的空间清零。

4.8 回调文件清理

(1) 手动关闭指定fd

遍历清理任务,找到ngx_pool_cleanup_file的handler,如果是要关闭的fd,则回调

void
ngx_pool_run_cleanup_file(ngx_pool_t *p, ngx_fd_t fd)
{
    ngx_pool_cleanup_t       *c;
    ngx_pool_cleanup_file_t  *cf;

    for (c = p->cleanup; c; c = c->next) {
        if (c->handler == ngx_pool_cleanup_file) {

            cf = c->data;

            if (cf->fd == fd) {
                c->handler(cf);
                c->handler = NULL;
                return;
            }
        }
    }
}
Nach dem Login kopieren
Nach dem Login kopieren

(2) 关闭fd

void
ngx_pool_cleanup_file(void *data)
{
    ngx_pool_cleanup_file_t  *c = data;

    ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, c->log, 0, "file cleanup: fd:%d",
                   c->fd);

    if (ngx_close_file(c->fd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                      ngx_close_file_n " \"%s\" failed", c->name);
    }
}
Nach dem Login kopieren
Nach dem Login kopieren

(3) 删除文件并关闭fd

void
ngx_pool_delete_file(void *data)
{
    ngx_pool_cleanup_file_t  *c = data;

    ngx_err_t  err;

    ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, c->log, 0, "file cleanup: fd:%d %s",
                   c->fd, c->name);

    if (ngx_delete_file(c->name) == NGX_FILE_ERROR) {
        err = ngx_errno;

        if (err != NGX_ENOENT) {
            ngx_log_error(NGX_LOG_CRIT, c->log, err,
                          ngx_delete_file_n " \"%s\" failed", c->name);
        }
    }

    if (ngx_close_file(c->fd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                      ngx_close_file_n " \"%s\" failed", c->name);
    }
}
Nach dem Login kopieren
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonSo implementieren Sie den Nginx-Speicherpool. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:yisu.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage