打开文件与共享内存链表初始化

2014-12-31 11:54:49   最后更新: 2014-12-31 11:57:31   访问数量:745




我们说过nginx 是通过资源集中管理的方式管理资源的,即打开所有即将要用的资源,以备随时取用,无论是文件还是内存

这样做的好处是避免了每次创建、打开资源造成的性能消耗

针对内存管理,nginx 设计了内存池结构,而针对打开的文件,在 ngx_cycle_t 类型中保存了打开文件链表,用来管理所有已经打开的文件,这样避免了每次打开文件的性能消耗

因此,在 ngx_cycle 初始化的过程中,很重要的一个环节就是复制所有 old_cycle 已经打开的文件

// 打开文件链表初始化 if (old_cycle->open_files.part.nelts) { n = old_cycle->open_files.part.nelts; for (part = old_cycle->open_files.part.next; part; part = part->next) { n += part->nelts; } } else { n = 20; } if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } // 内存链表初始化 if (old_cycle->shared_memory.part.nelts) { n = old_cycle->shared_memory.part.nelts; for (part = old_cycle->shared_memory.part.next; part; part = part->next) { n += part->nelts; } } else { n = 1; } if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; }

 

ngx_cycle_s 结构的 open_files 域是一个 ngx_list_t 结构

ngx_list_t 结构是 nginx 封装的链表结构

typedef struct ngx_list_part_s ngx_list_part_t; // struct ngx_list_part_s // 链表节点 {{{ struct ngx_list_part_s { void *elts; // 节点数组 ngx_uint_t nelts; // 节点元素个数 ngx_list_part_t *next; // 下一节点 }; // }}} // typedef struct ngx_list_t // nginx 链表结构(以数组为节点) {{{ typedef struct { ngx_list_part_t *last; // 最后一个节点 ngx_list_part_t part; // 首个节点 size_t size; // 单个节点占内存大小 ngx_uint_t nalloc; // 每个节点中数组的容量 ngx_pool_t *pool; // 为链表分配的内存池 } ngx_list_t; // }}}

 

确切的说,nginx 的链表结构更像是散列表,因为他的每个元素都是一个 ngx_list_part_s 类型的结构体,而这个类型的结构体其实是一个数组元素,这么做的好处在于,以散列的方式既能节约存储空间,又可以节省查找时间

// static ngx_inline ngx_int_t ngx_list_init(ngx_list_t *list, ngx_pool_t *pool, ngx_uint_t n, size_t size) // 链表初始化 {{{ static ngx_inline ngx_int_t ngx_list_init(ngx_list_t *list, ngx_pool_t *pool, ngx_uint_t n, size_t size) { list->part.elts = ngx_palloc(pool, n * size); if (list->part.elts == NULL) { return NGX_ERROR; } list->part.nelts = 0; list->part.next = NULL; list->last = &list->part; list->size = size; list->nalloc = n; list->pool = pool; return NGX_OK; } // }}}

 

这个函数在内存池中分配空间,并初始化了链表结构

// struct ngx_open_file_s // 打开文件结构 {{{ struct ngx_open_file_s { ngx_fd_t fd; ngx_str_t name; void (*flush)(ngx_open_file_t *file, ngx_log_t *log); // 文件刷新时调用的回调 void *data; // 回调函数使用的参数 }; // }}}

 

这个结构体保存了已经打开的文件的文件描述符与文件名,以及当文件刷新后需要调用的回调函数及其参数

// struct ngx_shm_t // 共享内存结构 {{{ typedef struct { u_char *addr; size_t size; ngx_str_t name; ngx_log_t *log; ngx_uint_t exists; /* unsigned exists:1; */ } ngx_shm_t; // }}} typedef struct ngx_shm_zone_s ngx_shm_zone_t; typedef ngx_int_t (*ngx_shm_zone_init_pt) (ngx_shm_zone_t *zone, void *data); // struct ngx_shm_zone_s // 共享内存空间 {{{ struct ngx_shm_zone_s { void *data; // 初始化回调函数所需的参数 ngx_shm_t shm; // 共享内存结构 ngx_shm_zone_init_pt init; // 初始化共享内存调用的回调函数 void *tag; // 标记 }; // }}}

 

这几个结构体描述了一块共享内存的地址、大小、名称、是否存在等信息,以及初始化共享内存需要调用的回调函数及其参数

 

这里可以看出来,nginx 服务器设计的一个原则就是 -- 异步+回调,这样做使得进程可以快速的处理事件,而无需等待事件处理完成,极大地增加了事件处理的灵活性

 






技术帖      linux      unix      龙潭书斋      服务器      文件      nginx      链表      ngx_list_t      ngx_list_init      ngx_open_file_t      ngx_shm_zone_t     


京ICP备15018585号