ngx_http_core_server

static char *
ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
{
    char                        *rv;
    void                        *mconf;
    size_t                       len;
    u_char                      *p;
    ngx_uint_t                   i;
    ngx_conf_t                   pcf;
    ngx_http_module_t           *module;
    struct sockaddr_in          *sin;
    ngx_http_conf_ctx_t         *ctx, *http_ctx;
    ngx_http_listen_opt_t        lsopt;
    ngx_http_core_srv_conf_t    *cscf, **cscfp;
    ngx_http_core_main_conf_t   *cmcf;

    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
    if (ctx == NULL) {
        return NGX_CONF_ERROR;
    }

    http_ctx = cf->ctx;
    ctx->main_conf = http_ctx->main_conf;

    /* the server{}'s srv_conf */

    ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->srv_conf == NULL) {
        return NGX_CONF_ERROR;
    }

    /* the server{}'s loc_conf */

    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->loc_conf == NULL) {
        return NGX_CONF_ERROR;
    }

    for (i = 0; cf->cycle->modules[i]; i++) {
        if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) {
            continue;
        }

        module = cf->cycle->modules[i]->ctx;

        if (module->create_srv_conf) {
            mconf = module->create_srv_conf(cf);
            if (mconf == NULL) {
                return NGX_CONF_ERROR;
            }

            ctx->srv_conf[cf->cycle->modules[i]->ctx_index] = mconf;
        }

        if (module->create_loc_conf) {
            mconf = module->create_loc_conf(cf);
            if (mconf == NULL) {
                return NGX_CONF_ERROR;
            }

            ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf;
        }
    }


    /* the server configuration context */

    cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
    cscf->ctx = ctx;


    cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];

    cscfp = ngx_array_push(&cmcf->servers);
    if (cscfp == NULL) {
        return NGX_CONF_ERROR;
    }

    *cscfp = cscf;


    /* parse inside server{} */

    pcf = *cf;
    cf->ctx = ctx;
    cf->cmd_type = NGX_HTTP_SRV_CONF;

    rv = ngx_conf_parse(cf, NULL);

    *cf = pcf;

    if (rv == NGX_CONF_OK && !cscf->listen) {
        ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t));

        p = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
        if (p == NULL) {
            return NGX_CONF_ERROR;
        }

        lsopt.sockaddr = (struct sockaddr *) p;

        sin = (struct sockaddr_in *) p;

        sin->sin_family = AF_INET;
#if (NGX_WIN32)
        sin->sin_port = htons(80);
#else
        sin->sin_port = htons((getuid() == 0) ? 80 : 8000);
#endif
        sin->sin_addr.s_addr = INADDR_ANY;

        lsopt.socklen = sizeof(struct sockaddr_in);

        lsopt.backlog = NGX_LISTEN_BACKLOG;
        lsopt.rcvbuf = -1;
        lsopt.sndbuf = -1;
#if (NGX_HAVE_SETFIB)
        lsopt.setfib = -1;
#endif
#if (NGX_HAVE_TCP_FASTOPEN)
        lsopt.fastopen = -1;
#endif
        lsopt.wildcard = 1;

        len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;

        p = ngx_pnalloc(cf->pool, len);
        if (p == NULL) {
            return NGX_CONF_ERROR;
        }

        lsopt.addr_text.data = p;
        lsopt.addr_text.len = ngx_sock_ntop(lsopt.sockaddr, lsopt.socklen, p,
                                            len, 1);

        if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) {
            return NGX_CONF_ERROR;
        }
    }

    return rv;
}

ngx_http_core_server 函数是 Nginx 在解析配置文件中 server{} 块时的核心处理函数


    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
    if (ctx == NULL) {
        return NGX_CONF_ERROR;
    }

server{} 块的配置上下文分配内存

ngx_http_conf_ctx_t 是 Nginx HTTP 配置的核心结构体,用于存储 server{} 块的配置上下文(包括 main_confsrv_confloc_conf 三个配置数组)

 

    http_ctx = cf->ctx;
    ctx->main_conf = http_ctx->main_conf;

在解析 server{} 块时,cf->ctx 指向的是全局的 HTTP 配置上下文(即 main 级别的配置上下文)。

通过赋值给 http_ctx,将全局上下文保存到临时变量中,避免后续因 cf->ctx 被修改而丢失对全局配置的引用。

http_ctx->main_conf 是全局 HTTP 配置中的 main_conf 数组,存储所有 HTTP 模块的 main 级配置。

ctx->main_conf 是当前 server{} 块上下文中的 main_conf 指针。

通过直接赋值,使 server{} 块的 main_conf 指向全局的 main_conf,实现配置继承

    /* the server{}'s srv_conf */

    ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->srv_conf == NULL) {
        return NGX_CONF_ERROR;
    }

server{} 块的 srv_conf 数组分配内存

   /* the server{}'s loc_conf */

    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->loc_conf == NULL) {
        return NGX_CONF_ERROR;
    }

server{} 块的 loc_conf 数组分配内存

 

    for (i = 0; cf->cycle->modules[i]; i++) {
        if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) {
            continue;
        }

 遍历,跳过非NGX_HTTP_MODULE模块

module = cf->cycle->modules[i]->ctx;

 获取模块的上下文

if (module->create_srv_conf) {
            mconf = module->create_srv_conf(cf);
            if (mconf == NULL) {
                return NGX_CONF_ERROR;
            }

            ctx->srv_conf[cf->cycle->modules[i]->ctx_index] = mconf;
        }

 create_srv_conf 是模块定义的函数指针,用于创建该模块的 server 级配置结构体

if (module->create_loc_conf) {
            mconf = module->create_loc_conf(cf);
            if (mconf == NULL) {
                return NGX_CONF_ERROR;
            }

            ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf;
        }

 用于创建该模块的 location 级配置结构体

    /* the server configuration context */

    cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
    cscf->ctx = ctx;

获取核心模块(ngx_http_core_module)的 server 级配置结构体

server{} 块的配置上下文(ctx)关联到核心模块的配置结构体

cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];

访问当前 server{} 块上下文中的 main_conf 数组

获取核心模块(ngx_http_core_module)的 main 级配置

ctx 是当前 server{} 块的配置上下文

main_conf ,指向全局的 main 级配置数组。

该数组存储了所有 HTTP 模块的 main 级配置结构体指针

配置继承 :server{} 块通过 main_conf 继承全局配置

全局数据访问 :main_conf 是全局唯一的,所有 server{} 块共享同一份 main_conf

 

    cscfp = ngx_array_push(&cmcf->servers);
    if (cscfp == NULL) {
        return NGX_CONF_ERROR;
    }

将当前 server{} 块的核心配置指针添加到全局服务器列表

cmcf->servers 是核心模块全局配置(ngx_http_core_main_conf_t)中的动态数组,存储所有 server{} 块的 ngx_http_core_srv_conf_t 指针。

*cscfp = cscf;

*cscfp = cscf 是将cscf的值(即当前server的核心配置结构体指针)存储到动态数组中的新位置 

将当前 server{} 块的核心配置指针赋值给动态数组中的新元素

 

    /* parse inside server{} */

    pcf = *cf;
    cf->ctx = ctx;
    cf->cmd_type = NGX_HTTP_SRV_CONF;

    rv = ngx_conf_parse(cf, NULL);

    *cf = pcf;

 保存当前配置解析上下文的状态

将配置解析上下文切换为当前 server{} 块的上下文

设置当前解析的指令类型为 server 级指令

递归解析 server{} 块内部的配置指令

恢复原始的配置解析上下文


进入 ngx_conf_parse 

else if (cf->conf_file->file.fd != NGX_INVALID_FILE) {

        type = parse_block;

进入这个条件

然后

   for ( ;; ) {
        rc = ngx_conf_read_token(cf);

 循环,读取 token

接下来读到的是

listen       80

;作为结束

然后

rc = ngx_conf_handler(cf, rc);

处理当前读取的 token


进入 ngx_conf_handler 

static ngx_int_t
ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
{
    char           *rv;
    void           *conf, **confp;
    ngx_uint_t      i, found;
    ngx_str_t      *name;
    ngx_command_t  *cmd;

    name = cf->args->elts;

    found = 0;

当前要处理的指令是 listen

name->data=listen

    for (i = 0; cf->cycle->modules[i]; i++) {

        cmd = cf->cycle->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;
            }

 循环,查找 listen 指令

直到

i=9

modules[9]->name=ngx_http_core_module

然后通过语法检查

接下来

            else if (cf->ctx) {
                confp = *(void **) ((char *) cf->ctx + cmd->conf);

                if (confp) {
                    conf = confp[cf->cycle->modules[i]->ctx_index];
                }
            }

此时

cmd->conf=8
ctx_index=0

cmd->conf 是一个关键字段,用于定位指令对应的配置存储位置

cmd->confngx_command_t 结构体中的一个字段,表示 配置存储的偏移量 。它决定了该指令的配置值应被存储到哪个配置块(如 mainserverlocation 等)的内存区域中。

此时 cf->ctx 指向一个 ngx_http_conf_ctx_t 结构体

ngx_http_conf_ctx_t -CSDN博客

(char *) cf->ctx + cmd->conf

也就是跳过了 结构体中的第一个字段,指向结构体的第二个字段 srv_conf

srv_conf 用来 存储 server 级别的配置数据 (当前正处于 server 块中)

接下来

 

rv = cmd->set(cf, cmd, conf);

 此时的 cmd->set 是 ngx_http_core_module 的 listen指令的set

是 ngx_http_core_listen

ngx_http_core_listen-CSDN博客


            if (rv == NGX_CONF_OK) {
                return NGX_OK;
            }

返回 NGX_OK 


回到 ngx_conf_parse

rc = ngx_conf_read_token(cf);

继续 读取配置文件 接下来的 token

接下来要读取的 token 是 37行的

server_name  localhost 以 ;为结束

server_name localhost; 是 Nginx 配置中的关键指令,用于定义虚拟主机(Virtual Host)的域名或标识符。它的核心作用是 根据 HTTP 请求的 Host 头字段匹配对应的服务器配置块 ,从而确保 Nginx 能正确路由请求到目标服务

rc = ngx_conf_handler(cf, rc);

 处理读取的 token


进入 ngx_conf_handler 

static ngx_int_t
ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
{
    char           *rv;
    void           *conf, **confp;
    ngx_uint_t      i, found;
    ngx_str_t      *name;
    ngx_command_t  *cmd;

    name = cf->args->elts;

    found = 0;

此时 name->data=server_name

此时要处理的指令是 server_name

    for (i = 0; cf->cycle->modules[i]; i++) {

        cmd = cf->cycle->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;

 遍历查找 server_name 指令

直到 i=9

modules[9]->name=ngx_http_core_module

在 ngx_http_core_module 模块中找到了 server_name 指令

cmd->name.data=server_name

然后通过语法检查之后

         else if (cf->ctx) {
                confp = *(void **) ((char *) cf->ctx + cmd->conf);

                if (confp) {
                    conf = confp[cf->cycle->modules[i]->ctx_index];
                }
            }

cmd->conf=8
ctx_index=0

            rv = cmd->set(cf, cmd, conf);

 此时的 cmd->set 是 ngx_http_core_module 模块的 server_name 指令 的set 函数指针

ngx_http_core_server_name

ngx_http_core_server_name-CSDN博客

            if (rv == NGX_CONF_OK) {
                return NGX_OK;
            }

 返回 NGX_OK


 回到 ngx_conf_parse

rc = ngx_conf_read_token(cf);

继续读取 token

跳过注释和空行 接下来是 43 行的

location / {

以{ 为结束

rc = ngx_conf_handler(cf, rc);

处理 token


 进入 ngx_conf_handler 

static ngx_int_t
ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
{
    char           *rv;
    void           *conf, **confp;
    ngx_uint_t      i, found;
    ngx_str_t      *name;
    ngx_command_t  *cmd;

    name = cf->args->elts;

    found = 0;

此时 name->data=location 

    for (i = 0; cf->cycle->modules[i]; i++) {

        cmd = cf->cycle->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;

 遍历查找 location 指令

直到

i=9

modules[9]->name=ngx_http_core_module

            else if (cf->ctx) {
                confp = *(void **) ((char *) cf->ctx + cmd->conf);

                if (confp) {
                    conf = confp[cf->cycle->modules[i]->ctx_index];
                }
            }

cmd->conf=8
ctx_index=0 

rv = cmd->set(cf, cmd, conf);

 此时 是ngx_http_core_module 模块的  location 指令 的set 函数指针

是 ngx_http_core_location

ngx_http_core_location-CSDN博客

            if (rv == NGX_CONF_OK) {
                return NGX_OK;
            }

 返回 NGX_OK


 回到 ngx_conf_parse

rc = ngx_conf_read_token(cf);

继续读取 token 

接下来读取的是

error_page   500 502 503 504  /50x.html

以 ;为结束

这行配置的作用是:当 Nginx 服务器遇到指定的 HTTP 错误状态码(500、502、503、504)时,自动将客户端请求重定向到自定义的错误页面 /50x.html ,而不是显示默认的 Nginx 错误页面

error_page
这是 Nginx 的指令,用于定义当服务器发生错误时返回的自定义页面。

500 502 503 504
这些是 HTTP 状态码,分别表示:

500 :内部服务器错误(Internal Server Error)。

502 :网关错误(Bad Gateway),通常由上游服务器(如 PHP、反向代理)响应无效内容导致。

503 :服务不可用(Service Unavailable),通常因服务器过载或维护触发。

504 :网关超时(Gateway Timeout),上游服务器未及时响应。

/50x.html
这是自定义错误页面的路径(相对于 Nginx 的根目录 root)。

 

rc = ngx_conf_handler(cf, rc);

处理读取的 token


进入 ngx_conf_handler 

static ngx_int_t
ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
{
    char           *rv;
    void           *conf, **confp;
    ngx_uint_t      i, found;
    ngx_str_t      *name;
    ngx_command_t  *cmd;

    name = cf->args->elts;

    found = 0;

此时 name->data=error_page

当前要处理的指令是 error_page

   for (i = 0; cf->cycle->modules[i]; i++) {

        cmd = cf->cycle->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;

 循环查找 error_page 指令

直到

i=9

modules[9]->name=ngx_http_core_module

            else if (cf->ctx) {
                confp = *(void **) ((char *) cf->ctx + cmd->conf);

                if (confp) {
                    conf = confp[cf->cycle->modules[i]->ctx_index];
                }
            }

获取对应的配置结构的指针

此时 

cmd->conf=16
ctx_index=0

rv = cmd->set(cf, cmd, conf);

 处理 token

此时 是 ngx_http_core_module 模块的 error_page 指令的 set

指向的是 ngx_http_core_error_page 

ngx_http_core_error_page-CSDN博客

            if (rv == NGX_CONF_OK) {
                return NGX_OK;
            }

返回 NGX_OK


  回到 ngx_conf_parse

rc = ngx_conf_read_token(cf);

继续读取 token

接下来要读取的 token 是 

53 行的

location = /50x.html

以 { 为结束

rc = ngx_conf_handler(cf, rc);

处理读取的 token


进入 ngx_conf_handler

static ngx_int_t
ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
{
    char           *rv;
    void           *conf, **confp;
    ngx_uint_t      i, found;
    ngx_str_t      *name;
    ngx_command_t  *cmd;

    name = cf->args->elts;

    found = 0;

此时 

name->data=location

    for (i = 0; cf->cycle->modules[i]; i++) {

        cmd = cf->cycle->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;

查找 location 指令

直到

i=9

modules[9]->name=ngx_http_core_module

           else if (cf->ctx) {
                confp = *(void **) ((char *) cf->ctx + cmd->conf);

                if (confp) {
                    conf = confp[cf->cycle->modules[i]->ctx_index];
                }
            }

 获取指针,指向对应的配置结构

此时

cmd->conf=8
ctx_index=0

rv = cmd->set(cf, cmd, conf);

 此时 是ngx_http_core_module 模块的  location 指令 的set 函数指针

是 ngx_http_core_location

 

ngx_http_core_location - 2-CSDN博客

            if (rv == NGX_CONF_OK) {
                return NGX_OK;
            }

返回 NGX_OK


   回到 ngx_conf_parse

rc = ngx_conf_read_token(cf);

继续读取 token  

接下来读取的是 79 行的

}

rc == NGX_CONF_BLOCK_DONE

        if (rc == NGX_CONF_BLOCK_DONE) {

            if (type != parse_block) {
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\"");
                goto failed;
            }

            goto done;
        }
done:

    if (filename) {
        if (cf->conf_file->buffer->start) {
            ngx_free(cf->conf_file->buffer->start);
        }

        if (ngx_close_file(fd) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
                          ngx_close_file_n " %s failed",
                          filename->data);
            rc = NGX_ERROR;
        }

        cf->conf_file = prev;
    }

    if (rc == NGX_ERROR) {
        return NGX_CONF_ERROR;
    }

    return NGX_CONF_OK;

filename=NULL

返回 NGX_CONF_OK

你可能感兴趣的:(nginx)