Heim >Backend-Entwicklung >PHP-Tutorial >[Analyse des Nginx-Quellcodes]Implementierung des Nginx-Speicherpools

[Analyse des Nginx-Quellcodes]Implementierung des Nginx-Speicherpools

WBOY
WBOYOriginal
2016-08-08 09:24:461142Durchsuche

Speicherpoolfunktion:

ngx_create_pool
ngx_destroy_pool
ngx_reset_pool
ngx_palloc
ngx_pnalloc
ngx_palloc_block
ngx_palloc_large
ngx_pool_cleanup_add

Speicherpoolerstellung

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);//按照16字节对齐分配一块size大小内存
      if (p == NULL) {
          return NULL;
      }                                                                                                                                                              
  
      p->d.last = (u_char *) p + sizeof(ngx_pool_t);  //last指向数据部分开始(跳过header ngx_pool_t)结构
      p->d.end = (u_char *) p + size;                 //end指向末尾结构
      p->d.next = NULL;                               //next是对小块内存链表管理指针
      p->d.failed = 0;                                //此块内存分配失败次数
  
      size = size - sizeof(ngx_pool_t);               //去掉ngx_pool_t内存池的实际大小
      p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;//最大内存池节点大小为4095
  
      p->current = p;                                 //current指向p
      p->chain = NULL;
      p->large = NULL;
      p->cleanup = NULL;
      p->log = log;
  
      return p;
  }

Die Initialisierungsstruktur ist wie folgt:

Die grüne Linie stellt das Strukturmitglied dar. Zu den Mitgliedern von ngx_pool_data_t gehören beispielsweise last, end, next, failed

Die schwarze Linie stellt die Adresse dar, auf die der Zeiger zeigt

1 max wird für size-sizeof(ngx_pool_t) und 4095 erstellt, wählen Sie das kleinste

2 Protokoll aus und rufen Sie die von ngx_log_init in main erstellte ngx_log_t-Struktur auf (dh das globale ngx_log-Objekt)

Prinzip :

nginx beginnt tatsächlich bei d.last. Da der Speicherpoolbereich extern zugewiesen wird, verschiebt sich die Ausrichtung dieses Felds nach hinten >Speicherpoolzuweisung

ngx_palloc () Versuchen Sie, Speicherplatz der Größe size aus dem Poolspeicherpool zuzuweisen. Es gibt zwei Situationen.
void *
 ngx_palloc(ngx_pool_t *pool, size_t size)
 {  
     u_char      *m;
     ngx_pool_t  *p;       
 
     //如果申请的内存大小小于创建的内存池节点大小(当然是去掉ngx_pool_t后)
     if (size <= pool->max) {
 
         p = pool->current;
 
         do {
             m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT);//首先对齐last指针
 
             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);
     }                                                                                                                                                              
 
     return ngx_palloc_large(pool, size);
 }

Wenn im ersten Fall die zugewiesene Größe kleiner als ngx_pool_t.max ist (kleine Blockzuweisung, Code 127-140), müssen Sie zuerst die letzten 16 Bits ausrichten, sofern noch Platz in der Anwendung vorhanden ist , dann verwenden Sie diesen Speicherknoten (d. h. Code 130). Bewegen Sie sich gleichzeitig als letzter, um auf die zugewiesene Adresse zu zeigen, und geben Sie den angeforderten Speicher an den Aufrufer zurück, wenn beim Durchlaufen der kleinen Speicherknoten kein Speicherplatz zugewiesen werden kann aktuell (d. h. Durchlaufen der verknüpften Liste, bis der nächste Speicherpoolknoten leer ist). Sie müssen einen Speicherpoolknoten zuweisen und ngx_palloc_block(pool,size) aufrufen

Diese Funktion weist hauptsächlich einen Speicherpoolknoten zu, fügt diesen Knoten dann am Ende der verknüpften Liste ein und aktualisiert den Pool-> Der aktuelle Zeiger wird gleichzeitig durchquert. Wenn in der verknüpften Liste festgestellt wird, dass dieser Knoten sechsmal nicht zugewiesen werden konnte, zeigt der aktuelle Zeiger auf den nächsten Knoten. current zeigt auf den neu zugewiesenen Knoten.

Der Kerncode lautet wie folgt:

current = pool->current;//初始化
 
     for (p = current; p->d.next; p = p->d.next) {//遍历
         if (p->d.failed++ > 4) {//分配超过6次
             current = p->d.next;
         }
     }
 
     p->d.next = new;//插入新节点                                                                                                                          
 
     pool->current = current ? current : new;//更新current

Ordnen Sie im zweiten Fall einen großen Teil des Speichers zu und rufen Sie nach der Zuweisung direkt malloc auf, um ihn zuzuweisen. Durchlaufen Sie die Pool-> große verknüpfte Liste. Wenn ein großer Speicherpoolknoten vorhanden ist und die Zuordnung leer ist, wird der neu zugewiesene Speicher an diesem Knoten aufgehängt. Wenn kein solcher Knoten vorhanden ist, wird der Kopf der verknüpften Liste p ->large wird zugewiesen und eingefügt.

Rückruffunktion löschen

wobei jeder Knoten

 struct ngx_pool_cleanup_s {
      ngx_pool_cleanup_pt   handler;//回调handler
      void                 *data;	//回调函数参数
      ngx_pool_cleanup_t   *next;	//指向下一个节点
  };
ist
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;                                                                                                                                                      
 }
Das Obige stellt die Implementierung des Nginx-Speicherpools einschließlich Aspekten des Inhalts vor. Ich hoffe, dass es für Freunde hilfreich ist, die sich für PHP-Tutorials interessieren.

Stellungnahme:
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