您的位置:首页 > 理论基础 > 数据结构算法

Nginx 代码解析(2) : 主要数据结构解析

2015-12-08 22:36 537 查看

Nginx 主要数据结构解析

本篇主要分析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类型的重新封装主要是为了更方便的使用。

核心数据结构 : 通用型

ngx_log_t : typedef struct ngx_log_s ngx_log_t;

其定义如下 :

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

ngx_pool_t : typedef struct ngx_pool_s ngx_pool_t;

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成员来管理,这里就不再详细描述了。

ngx_array_t :

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数据结构

ngx_list_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 等数据结构。

ngx_queue_t : typedef struct ngx_queue_s ngx_queue_t

18 struct ngx_queue_s {

19 ngx_queue_t *prev;

20 ngx_queue_t *next;

21 };

ngx_queue_t 是一个简单的数据结构,但是用处比较广泛,主要用来管理reusable_connections_queue。

ngx_buf_t: typedef struct ngx_buf_s ngx_buf_t

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 用来管理缓冲区的数据结构,基本上所有涉及到对缓冲区的操作,比如读,写,控制等,都需要用到这个结构。

核心数据结构 : 业务型

ngx_cycle_t : typedef struct ngx_cycle_s ngx_cycle_t

此数据结构是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 };

ngx_module_t : typedef struct ngx_module_s ngx_module_t

此数据结构是nginx的核心数据结构之一,定义了nginx的模块信息。

102 struct ngx_module_s {

103 ngx_uint_t ctx_index;

104 ngx_uint_t index;

105

106 ngx_uint_t spare0;

107 ngx_uint_t spare1;

108 ngx_uint_t spare2;

109 ngx_uint_t spare3;

110

111 ngx_uint_t version;

112

113 void *ctx;

114 ngx_command_t *commands;

115 ngx_uint_t type;

116

117 ngx_int_t (*init_master)(ngx_log_t *log);

118

119 ngx_int_t (*init_module)(ngx_cycle_t *cycle);

120

121 ngx_int_t (*init_process)(ngx_cycle_t *cycle);

122 ngx_int_t (*init_thread)(ngx_cycle_t *cycle);

123 void (*exit_thread)(ngx_cycle_t *cycle);

124 void (*exit_process)(ngx_cycle_t *cycle);

125

126 void (*exit_master)(ngx_cycle_t *cycle);

127

128 uintptr_t spare_hook0;

129 uintptr_t spare_hook1;

130 uintptr_t spare_hook2;

131 uintptr_t spare_hook3;

132 uintptr_t spare_hook4;

133 uintptr_t spare_hook5;

134 uintptr_t spare_hook6;

135 uintptr_t spare_hook7;

136 };

ngx_conf_t : typedef struct ngx_conf_s ngx_conf_t

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核心配置文件管理数据结构。



ngx_event_t : typedef struct ngx_event_s ngx_event_t

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 };

ngx_connection_t : typedef struct ngx_connection_s ngx_connection_t

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 };

非核心数据结构

ngx_core_conf_t : nginx运行的全局配置,定义在配置文件中

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;

Nginx用到的重要的全局变量(数据结构)

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默认的所有模块。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: