分类: 架构设计与优化
2014-11-06 16:32:53
本篇主要分析nginx代码中用到的主要的数据结构。
Nginx对自用数据结构的定义非常规范,统一,考虑也很周全,非常好的适配了linux, windows两个主流的OS,同时也很好的规避了32/64位机器的风险。另一方面,nginx的数据结构定义风格非常新颖,统一,
看得出作者的C语言是大师级的水平,通过分析nginx的数据结构的定义,我们一定可以学习到很多东西。
Nginx 大量使用了自定义的基础数据结构,其主要目的是对C语言中基础的数据结构类型进行二次封装,以达到统一风格,规避风险以及方便使用的问题,例如 :
78 typedef intptr_t ngx_int_t;
79 typedef uintptr_t ngx_uint_t;
80 typedef intptr_t ngx_flag_t;
nginx对于这列数据结构的定义主要是为了方便在32/64位机器之间的编译移植, 具体定义可参考 : /usr/include/stdint.h
16 typedef struct {
17 size_t len;
18 u_char *data;
19 } ngx_str_t;
nginx队char类型的重新封装主要是为了更方便的使用。
其定义如下 :
48 struct ngx_log_s {
49 ngx_uint_t log_level; // log 等级
50 ngx_open_file_t *file; // log打开的文件
51
52 ngx_atomic_uint_t connection;
53
54 ngx_log_handler_pt handler; // log处理函数
55 void *data; // 数据
56
57 /*
58 * we declare "action" as "char *" because the actions are usually
59 * the static strings and in the "u_char *" case we have to override
60 * their types all the time
61 */
62
63 char *action; // 泛型指针
64
65 ngx_log_t *next;
66 };
67
Nginx的pool数据结构,是nginx的核心数据结构之一,其目的是提供一个容器,以方便对内存,文件句柄等资源进行预分配,管理,回收等操作,其主要作用是队内存的管理。
43 struct ngx_pool_large_s {
44 ngx_pool_large_t *next;
45 void *alloc;
46 };
34 struct ngx_pool_cleanup_s {
35 ngx_pool_cleanup_pt handler;
36 void *data;
37 ngx_pool_cleanup_t *next;
38 };
49 typedef struct {
50 u_char *last;
51 u_char *end;
52 ngx_pool_t *next;
53 ngx_uint_t failed;
54 } ngx_pool_data_t;
57 struct ngx_pool_s {
58 ngx_pool_data_t d;
59 size_t max;
60 ngx_pool_t *current;
61 ngx_chain_t *chain;
62 ngx_pool_large_t *large;
63 ngx_pool_cleanup_t *cleanup;
64 ngx_log_t *log;
65 };
这个数据结构是一个管理数据结构,其中最终要的是‘d'成员。我们总是尾poll分配一定的内存空间大小(其必须大于pool本身的size),其中
d.last指向poll结构体本身占用空间之外的第一个字节,d.end只想整个分配空间的最后一个字节。Nginx定义了函数 :
nginx_create_poll(size, log)来分配一个pool,
需要注意的是成员max,其意思是此pool中除去pool本身大小外剩余的内存空间大小。
Nginx定义了函数 :
nginx_pnalloc(pool, size)
来从pool中分配内存。其核心思想是,检查pool中的剩余内存大小是否大于或等于size,如果是则从当前的pool直接分配,否则找到此pool链
表的下一个pool继续上一步骤。
需要注意的是pool是一个链表,依靠pool->d.next来进行组织。如果在当前pool的链中找不到合适的块,nginx会新分配一个
pool并将其链接到次pool的链表中来。需要注意的是,此pool的后继item(除链表头以外)只需要
ngx_pool_data_t 这个成员,其它部分都作为空闲内存空间使用。
large的分配是相似的,利用了pool中的large成员来管理,这里就不再详细描述了。
16 typedef struct {
17 void *elts;
18 ngx_uint_t nelts;
19 size_t size;
20 ngx_uint_t nalloc;
21 ngx_pool_t *pool;
22 } ngx_array_t;
ngx_array_t 是另外一个nginx组织数据的核心数据结构。其主要用途是用来管理一个数组,包括数组内存空间分配以及管理操作功能。
ngx_array_init(array, pool, n, size), ngx_array_t必须从与其关联的pool中为数组分配内存,
数组大小为n *
size,其中size是array所管理的数组中单个元素的大小n是元素的最大数目。poll是与array关联的pool的指针。实际所分配的内存空
间由elts指针管理。需要注意的是,array也有再分配功能,即当前array已满后,再次申请时需要对其内存大小进行调整,可能会有拷贝。
其管理函数主要有ngx_array_init, ngx_array_destroy, ngx_array_push, ngx_array_push_n等,这里就不再详细描述了。
ngx_array_t 主要用来管理 ngx_listening_t数据结构
18 struct ngx_list_part_s {
19 void *elts;
20 ngx_uint_t nelts;
21 ngx_list_part_t *next;
22 };
25 typedef struct {
26 ngx_list_part_t *last;
27 ngx_list_part_t part;
28 size_t size;
29 ngx_uint_t nalloc;
30 ngx_pool_t *pool;
31 } ngx_list_t;
ngx_list_t 是nginx中另外一个常用的核心数据结构。其用法与定义与ngx_array_t相差无几,这里就不再详细描述了。
ngx_list_t主要用来管理ngx_open_file_t,ngx_shm_zone_t 等数据结构。
18 struct ngx_queue_s {
19 ngx_queue_t *prev;
20 ngx_queue_t *next;
21 };
ngx_queue_t 是一个简单的数据结构,但是用处比较广泛,主要用来管理reusable_connections_queue。
20 struct ngx_buf_s {
21 u_char *pos;
22 u_char *last;
23 off_t file_pos;
24 off_t file_last;
25
26 u_char *start; /* start of buffer */
27 u_char *end; /* end of buffer */
28 ngx_buf_tag_t tag;
29 ngx_file_t *file;
30 ngx_buf_t *shadow;
31
32
33 /* the buf's content could be changed */
34 unsigned temporary:1;
35
36 /*
37 * the buf's content is in a memory cache or in a read only memory
38 * and must not be changed
39 */
40 unsigned memory:1;
41
42 /* the buf's content is mmap()ed and must not be changed */
43 unsigned mmap:1;
44
45 unsigned recycled:1;
46 unsigned in_file:1;
47 unsigned flush:1;
48 unsigned sync:1;
49 unsigned last_buf:1;
50 unsigned last_in_chain:1;
51
52 unsigned last_shadow:1;
53 unsigned temp_file:1;
54
55 /* STUB */ int num;
56 };
ngx_buf_t 是nginx 用来管理缓冲区的数据结构,基本上所有涉及到对缓冲区的操作,比如读,写,控制等,都需要用到这个结构。
此数据结构是nginx的主控数据结构,可以说是nginx全局运行的控制核心。
37 struct ngx_cycle_s {
38 void ****conf_ctx;
39 ngx_pool_t *pool; // 相关联的pool
40
41 ngx_log_t *log; // 所使用的log
42 ngx_log_t new_log;
43
44 ngx_uint_t log_use_stderr; /* unsigned log_use_stderr:1; */
45
46 ngx_connection_t **files;
47 ngx_connection_t *free_connections;
48 ngx_uint_t free_connection_n;
49
50 ngx_queue_t reusable_connections_queue;
51
52 ngx_array_t listening;
53 ngx_array_t paths;
54 ngx_list_t open_files;
55 ngx_list_t shared_memory;
56
57 ngx_uint_t connection_n;
58 ngx_uint_t files_n;
59
60 ngx_connection_t *connections;
61 ngx_event_t *read_events;
62 ngx_event_t *write_events;
63
64 ngx_cycle_t *old_cycle;
65
66 ngx_str_t conf_file;
67 ngx_str_t conf_param;
68 ngx_str_t conf_prefix;
69 ngx_str_t prefix;
70 ngx_str_t lock_file;
71 ngx_str_t hostname;
72 };
157 struct ngx_conf_s {
158 char *name;
159 ngx_array_t *args;
160
161 ngx_cycle_t *cycle;
162 ngx_pool_t *pool;
163 ngx_pool_t *temp_pool;
164 ngx_conf_file_t *conf_file;
165 ngx_log_t *log;
166
167 void *ctx;
168 ngx_uint_t module_type;
169 ngx_uint_t cmd_type;
170
171 ngx_conf_handler_pt handler;
172 char *handler_conf;
173 };
ngx_conf_t是nginx核心配置文件管理数据结构。
38 struct ngx_event_s {
39 void *data;
40
41 unsigned write:1;
42
43 unsigned accept:1;
44
45 /* used to detect the stale events in kqueue, rtsig, and epoll */
46 unsigned instance:1;
47
48 /*
49 * the event was passed or would be passed to a kernel;
50 * in aio mode - operation was posted.
51 */
52 unsigned active:1;
53
54 unsigned disabled:1;
55
56 /* the ready event; in aio mode 0 means that no operation can be posted */
57 unsigned ready:1;
58
59 unsigned oneshot:1;
60
61 /* aio operation is complete */
62 unsigned complete:1;
63
64 unsigned eof:1;
65 unsigned error:1;
66
67 unsigned timedout:1;
68 unsigned timer_set:1;
69
70 unsigned delayed:1;
71
72 unsigned deferred_accept:1;
73
74 /* the pending eof reported by kqueue, epoll or in aio chain operation */
75 unsigned pending_eof:1;
76
77 #if !(NGX_THREADS)
78 unsigned posted_ready:1;
79 #endif
80
81 #if (NGX_WIN32)
82 /* setsockopt(SO_UPDATE_ACCEPT_CONTEXT) was successful */
83 unsigned accept_context_updated:1;
84 #endif
85
86 #if (NGX_HAVE_KQUEUE)
87 unsigned kq_vnode:1;
88
89 /* the pending errno reported by kqueue */
90 int kq_errno;
91 #endif
92
93 /*
94 * kqueue only:
95 * accept: number of sockets that wait to be accepted
96 * read: bytes to read when event is ready
97 * or lowat when event is set with NGX_LOWAT_EVENT flag
98 * write: available space in buffer when event is ready
99 * or lowat when event is set with NGX_LOWAT_EVENT flag
100 *
101 * iocp: TODO
102 *
103 * otherwise:
104 * accept: 1 if accept many, 0 otherwise
105 */
106
107 #if (NGX_HAVE_KQUEUE) || (NGX_HAVE_IOCP)
108 int available;
109 #else
110 unsigned available:1;
111 #endif
112
113 ngx_event_handler_pt handler;
114
115
116 #if (NGX_HAVE_AIO)
117
118 #if (NGX_HAVE_IOCP)
119 ngx_event_ovlp_t ovlp;
120 #else
121 struct aiocb aiocb;
122 #endif
123
124 #endif
125
126 ngx_uint_t index;
127
128 ngx_log_t *log;
129
130 ngx_rbtree_node_t timer;
131
132 unsigned closed:1;
133
134 /* to test on worker exit */
135 unsigned channel:1;
136 unsigned resolver:1;
137
138 #if (NGX_THREADS)
139
140 unsigned locked:1;
141
142 unsigned posted_ready:1;
143 unsigned posted_timedout:1;
144 unsigned posted_eof:1;
145
146 #if (NGX_HAVE_KQUEUE)
147 /* the pending errno reported by kqueue */
148 int posted_errno;
149 #endif
150
151 #if (NGX_HAVE_KQUEUE) || (NGX_HAVE_IOCP)
152 int posted_available;
153 #else
154 unsigned posted_available:1;
155 #endif
156
157 ngx_atomic_t *lock;
158 ngx_atomic_t *own_lock;
159
160 #endif
161
162 /* the links of the posted queue */
163 ngx_event_t *next;
164 ngx_event_t **prev;
165
167 #if 0
168
169 /* the threads support */
170
171 /*
172 * the event thread context, we store it here
173 * if $(CC) does not understand __thread declaration
174 * and pthread_getspecific() is too costly
175 */
176
177 void *thr_ctx;
178
179 #if (NGX_EVENT_T_PADDING)
180
181 /* event should not cross cache line in SMP */
182
183 uint32_t padding[NGX_EVENT_T_PADDING];
184 #endif
185 #endif
186 };
118 struct ngx_connection_s {
119 void *data;
120 ngx_event_t *read;
121 ngx_event_t *write;
122
123 ngx_socket_t fd;
124
125 ngx_recv_pt recv;
126 ngx_send_pt send;
127 ngx_recv_chain_pt recv_chain;
128 ngx_send_chain_pt send_chain;
129
130 ngx_listening_t *listening;
131
132 off_t sent;
133
134 ngx_log_t *log;
135
136 ngx_pool_t *pool;
137
138 struct sockaddr *sockaddr;
139 socklen_t socklen;
140 ngx_str_t addr_text;
141
142 ngx_str_t proxy_protocol_addr;
143
144 #if (NGX_SSL)
145 ngx_ssl_connection_t *ssl;
146 #endif
147
148 struct sockaddr *local_sockaddr;
149 socklen_t local_socklen;
150
151 ngx_buf_t *buffer;
152
153 ngx_queue_t queue;
154
155 ngx_atomic_uint_t number;
156
157 ngx_uint_t requests;
158
159 unsigned buffered:8;
160
161 unsigned log_error:3; /* ngx_connection_log_error_e */
162
163 unsigned unexpected_eof:1;
164 unsigned timedout:1;
165 unsigned error:1;
166 unsigned destroyed:1;
167
168 unsigned idle:1;
169 unsigned reusable:1;
170 unsigned close:1;
171
172 unsigned sendfile:1;
173 unsigned sndlowat:1;
174 unsigned tcp_nodelay:2; /* ngx_connection_tcp_nodelay_e */
175 unsigned tcp_nopush:2; /* ngx_connection_tcp_nopush_e */
176
177 unsigned need_last_buf:1;
178
179 #if (NGX_HAVE_IOCP)
180 unsigned accept_context_updated:1;
181 #endif
182
183 #if (NGX_HAVE_AIO_SENDFILE)
184 unsigned aio_sendfile:1;
185 unsigned busy_count:2;
186 ngx_buf_t *busy_sendfile;
187 #endif
188
189 #if (NGX_THREADS)
190 ngx_atomic_t lock;
191 #endif
192 };
75 typedef struct {
76 ngx_flag_t daemon;
77 ngx_flag_t master;
78
79 ngx_msec_t timer_resolution;
80
81 ngx_int_t worker_processes;
82 ngx_int_t debug_points;
83
84 ngx_int_t rlimit_nofile;
85 ngx_int_t rlimit_sigpending;
86 off_t rlimit_core;
87
88 int priority;
89
90 ngx_uint_t cpu_affinity_n;
91 uint64_t *cpu_affinity;
92
93 char *username;
94 ngx_uid_t user;
95 ngx_gid_t group;
96
97 ngx_str_t working_directory;
98 ngx_str_t lock_file;
99
100 ngx_str_t pid;
101 ngx_str_t oldpid;
102
103 ngx_array_t env;
104 char **environment;
105
106 #if (NGX_THREADS)
107 ngx_int_t worker_threads;
108 size_t thread_stack_size;
109 #endif
110
111 } ngx_core_conf_t;
ngx_sys_errlist : 用来储存全局的错误信息描述,主要是为了提高效率与便于管理
ngx_max_sockets : 暂时位用
ngx_log : 全局的log变量
init_cycle : 全局的cycle变量,注意此变量只在初始化时候使用!
ngx_cycle : 全局cycle变量,是运行时的cycle
ngx_max_module : 全局module个数变量
ngx_modules【】 : nginx的模块定义列表,在nginx/objs/ngx_modules.c中定义,此全局数组定义了nginx默认的所有模块。