Nginx 고급 데이터 구조 소스 분석 (4) --- 메모리 풀
9443 단어 nginx
몇 가지 관건 적 인 지식 포 인 트 는 다음 과 같다.
(1) 함수 ngxpalloc () 는 메모리 에서 size 크기 의 메모 리 를 분배 하려 고 할 때 두 가지 상황 으로 나 누 었 습 니 다. 하 나 는 size 크기 가 pool - > max 보다 작 으 면 작은 메모리 분배 라 고 합 니 다. 현재 메모리 탱크 노드 가 size 보다 작 으 면 같은 크기 의 메모리 탱크 노드 를 신청 한 다음 에 이 새 메모리 탱크 노드 에서 size 크기 의 메모리 공간 을 분배 합 니 다.만약 size 가 pool - > max 보다 크 면 큰 메모 리 를 분배 합 니 다. 이때 호출 된 함 수 는 운영 체제 에 큰 메모 리 를 직접 신청 합 니 다.
(2) 작은 블록 메모리 의 신청 은 링크 의 끝 부분 에 삽입 되 고 새로운 큰 블록 메모 리 는 링크 앞 에 삽입 된다.
(3) Nginx 는 큰 메모리 에 대한 방출 만 제공 하고 작은 메모리 에 대한 방출 을 제공 하지 않 는 다. 이 는 메모리 풀 에서 분 배 된 메모리 가 메모리 풀 로 회수 되 지 않 고 전체 메모리 풀 을 소각 할 때 만 시스템 메모리 로 회수 된다 는 것 을 의미한다.
(4)ngx_pool_t 의 current 필드: 이 필드 는 메모리 풀 에서 메모 리 를 분배 하 는 시작 노드 를 기록 합 니 다. Nginx 는 메모리 노드 의 총 실패 횟수 가 6 번 이상 일 때 current 는 다음 메모리 노드 를 가리 키 도록 규정 합 니 다.
(5) pool - > max 필드 의 최대 치 를 한 페이지 의 메모리 로 제한 하 는 이 유 는 작은 메모리 와 큰 메모리 의 임계 이기 도 합 니 다. 분 배 된 공간 이 한 페이지 보다 작 을 때 만 캐 시 할 필요 가 있 기 때 문 입 니 다. 그렇지 않 으 면 시스템 인터페이스 malloc () 를 이용 하여 운영 체제 에 직접 신청 하 는 것 이 좋 습 니 다.
각 구조 체 의 정의:
//
struct ngx_pool_large_s {
ngx_pool_large_t *next; //
void *alloc; //
};
//
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; // , 1
ngx_pool_t *current; //
ngx_chain_t *chain;
ngx_pool_large_t *large; //
ngx_pool_cleanup_t *cleanup; //
ngx_log_t *log;
};
메모리 풀 초기 화:
// size
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); // size
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; // , 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;
}
메모리 탱크 의 소각 과 초기 화:
//
void
ngx_destroy_pool(ngx_pool_t *pool)
{
ngx_pool_t *p, *n;
ngx_pool_large_t *l;
ngx_pool_cleanup_t *c;
// handler
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) {
ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "free: %p", l->alloc);
if (l->alloc) {
ngx_free(l->alloc); // free malloc
}
}
#if (NGX_DEBUG)
/*
* we could allocate the pool->log from this pool
* so we cannot use this log while free()ing the pool
*/
for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
"free: %p, unused: %uz", p, p->d.end - p->d.last);
if (n == NULL) {
break;
}
}
#endif
// ngx_pool_t
for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
ngx_free(p);
if (n == NULL) {
break;
}
}
}
//
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);
}
}
// , last
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;
}
할당 메모리:
// ( )
void *
ngx_palloc(ngx_pool_t *pool, size_t size)
{
u_char *m;
ngx_pool_t *p;
if (size <= pool->max) { // , size
p = pool->current;
do {
m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT); // d.last
if ((size_t) (p->d.end - m) >= size) { //
p->d.last = m + size; // d.last
return m; //
}
p = p->d.next; //
} while (p);
// ,
return ngx_palloc_block(pool, size);
}
return ngx_palloc_large(pool, size); //
}
// ( )
void *
ngx_pnalloc(ngx_pool_t *pool, size_t size)
{
u_char *m;
ngx_pool_t *p;
if (size <= pool->max) { //
p = pool->current;
do {
m = p->d.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); //
}
작은 블록 메모리 할당:
//
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); // ngx_pool_data_t, ngx_pool_t
m = ngx_align_ptr(m, NGX_ALIGNMENT);
new->d.last = m + size; //
// 5 , 6 ,current
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;
}
블록 메모리 할당
//
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); // malloc
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) { // 4 , 5 break,
break;
}
}
large = ngx_palloc(pool, sizeof(ngx_pool_large_t)); //
if (large == NULL) {
ngx_free(p);
return NULL;
}
large->alloc = p; //
// large
large->next = pool->large;
pool->large = large;
return p;
}
직접 할당 메모리:
// ,
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(pool, sizeof(ngx_pool_large_t)); //
if (large == NULL) {
ngx_free(p);
return NULL;
}
// ngx_pool_t
large->alloc = p; //
//
large->next = pool->large;
pool->large = large;
return p;
}
메모리 사용:
//
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;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
간단! Certbot을 사용하여 웹 사이트를 SSL(HTTPS)화하는 방법초보자가 인프라 주위를 정돈하는 것은 매우 어렵습니다. 이번은 사이트를 간단하게 SSL화(HTTP에서 HTTPS통신)로 변경하는 방법을 소개합니다! 이번에는 소프트웨어 시스템 Nginx CentOS7 의 환경에서 S...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.