看了nginx代码,感觉应该写点什么,记下来,自己以后慢慢看,很多还是浅浅的懂了那么点点
看代码,首先进入的当然是main函数了,
nginx.c -> main()
进入后,是一堆的一些init初始化
if (ngx_strerror_init() != NGX_OK) {
return 1;
}
if (ngx_get_options(argc, argv) != NGX_OK) {
return 1;
}
局部变量有一个cycle, init_cycle
看代码可以看到,起初把一些配置信息都是放到init_cycle里面,然后通过
cycle = ngx_init_cycle(&init_cycle);
把需要的本模块的配置指令都返回到cycle里面,形成一个全新的配置信息;
看代码的时候在 ngx_init_cycle(&init_cycle)之前,会有
ngx_max_module = 0;
for (i = 0; ngx_modules[i]; i++) {
ngx_modules[i]->index = ngx_max_module++;
}
这个地方主要是做了一个统计,统计一下最大的ngx_max_module量,同时呢,赋值每一个ngx_modules的index变量; ngx_modules是一个全局的数组,存放着每一个模块的地址;查看源码的时候发现找ngx_modules的时候一直找不到,只有一个地方声明了一下,没有地方实现!!那怎么来了这么多地址呢,实际上,ngx在执行configur脚本的时候,会自动的把所要添加的模块,放到ngx_modules数组里面,进行定义,在configur后,生成一个objs/ngx_modules.c里面,如果你打开这个文件后,你就自然明白了;
接着往下走,进入
cycle = ngx_init_cycle(&init_cycle);
这个主要初始化一些ngx的配置信息,及把一些指令里面的函数钩子都进行赋值和实现;
下面看看这个函数吧,
进入后,发现刚开始就是把一些old_cycle赋值给新的cycle
cycle->pool = pool;
cycle->log = log;
cycle->old_cycle = old_cycle;
cycle->conf_prefix.len = old_cycle->conf_prefix.len;
cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix);
if (cycle->conf_prefix.data == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
初始化一个文件的list,ngx的list结构我在这里就不多说了,可以自己查看一下,
主要有一个数组存储信息,同事有一个n 和size表示数据的容纳的最大个数和数组的大小,在ngx_list_part_t数组里面有个nelts ,表示数据已经容纳多少个了,具体可以自己下去再查看查看;
if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))
!= NGX_OK)
{
ngx_destroy_pool(pool);
return NULL;
}
接着下面走,
if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
看到这俩个部分,重点在ngx_conf_parse里面, 把配置文件名,穿进去,然后进行一行行的解析,
进入 ngx_conf_parse看到
rc = ngx_conf_read_token(cf);
这个主要就是读取每一行,如果配置正确就返回正确的值,并保存配置指令及参数的值
然后下面调用
rc = ngx_conf_handler(cf, rc);
开始查找指令为name的module, 然后找到后,进行下一步
for (i = 0; ngx_modules[i]; i++) {
cmd = ngx_modules[i]->commands;
if (cmd == NULL) {
continue;
}
for ( /* void */ ; cmd->name.len; cmd++) {
if (name->len != cmd->name.len) {
continue;
}
if (ngx_strcmp(name->data, cmd->name.data) != 0) {
continue;
}
found = 1;
判断参数是否满足指令块的配置, 这在写模块的时候,里面都有指定
if (!(cmd->type & NGX_CONF_ANY)) {
if (cmd->type & NGX_CONF_FLAG) {
if (cf->args->nelts != 2) {
goto invalid;
}
} else if (cmd->type & NGX_CONF_1MORE) {
if (cf->args->nelts < 2) {
goto invalid;
}
} else if (cmd->type & NGX_CONF_2MORE) {
if (cf->args->nelts < 3) {
goto invalid;
}
当上面一切条件满足后,开始调用
rv = cmd->set(cf, cmd, conf);
执行模块挂上钩子信息;这个set方法具体实现是在你的模块里面实现的;
然后配置基本完毕,返回;
返回到main函数里面继续下一步,然后开始初始化其余的信息;进程信息 等等!!