Nginx源码阅读(main)

原帖地址:https://blog.csdn.net/hz5034/article/details/54630909

main()执行流程

main()代码解析

/* src/core/nginx.c */

int ngx_cdecl // #define ngx_cdecl,一个空的define,跨平台支持
main(int argc, char *const *argv)
{
    ngx_buf_t        *b;
    ngx_log_t        *log;
    ngx_uint_t        i;
    ngx_cycle_t      *cycle, init_cycle;
    ngx_conf_dump_t  *cd;
    ngx_core_conf_t  *ccf;

    ngx_debug_init(); // 在Linux系统中,#define ngx_debug_init(),一个空的define

    /* 创建一个包含NGX_SYS_NERR个ngx_str_t的数组ngx_sys_errlist,用于记录错误码[0,NGX_SYS_NERR-1]对应的错误信息
       NGX_SYS_NERR定义在objs/ngx_auto_config.h中,这是一个auto性质的文件,只有在执行了./configure后才能生成这个文件
       在Linux系统中NGX_SYS_NERR=132,表示有132个错误码 */
    if (ngx_strerror_init() != NGX_OK) {
        return 1;
    }

    // 解析命令行参数,对于-s,ngx_process = NGX_PROCESS_SIGNALLER;
    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }

    if (ngx_show_version) {
        ngx_show_version_info();

        if (!ngx_test_config) {
            return 0;
        }
    }

    /* TODO */ ngx_max_sockets = -1; // extern ngx_int_t ngx_max_sockets;

    ngx_time_init(); // 初始化时间

#if (NGX_PCRE)
    ngx_regex_init(); // 若启用了PCRE(Perl Compatible Regular Expressions),则初始化正则表达式
#endif

    ngx_pid = ngx_getpid(); // #define ngx_getpid getpid

    log = ngx_log_init(ngx_prefix); // 初始化日志
    if (log == NULL) {
        return 1;
    }

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init(log); // 若启用了NGX_OPENSSL,则初始化ssl
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); // 清零init_cycle
    init_cycle.log = log;
    ngx_cycle = &init_cycle; // volatile ngx_cycle_t *ngx_cycle;

    init_cycle.pool = ngx_create_pool(1024, log); // 创建大小为1024B的内存池
    if (init_cycle.pool == NULL) {
        return 1;
    }

    // 将命令行参数保存到全局变量ngx_argv中
    if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
        return 1;
    }

    // 初始化init_cycle的conf_prefix、prefix、conf_file、conf_param等
    if (ngx_process_options(&init_cycle) != NGX_OK) {
        return 1;
    }

    // 初始化系统变量ngx_pagesize、ngx_cacheline_size、ngx_max_sockets等
    if (ngx_os_init(log) != NGX_OK) {
        return 1;
    }

    /*
     * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
     */

    // 初始化CRC(Cyclic Redundancy Check)表,缓存对齐
    if (ngx_crc32_table_init() != NGX_OK) {
        return 1;
    }

    // 将环境变量NGINX中的socket保存到init_cycle的listening数组中
    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
        return 1;
    }

    // 遍历全局数组ngx_modules,根据各模块在ngx_modules中的顺序,设置各模块的index
    if (ngx_preinit_modules() != NGX_OK) {
        return 1;
    }

    // 初始化init_cycle,详见数据结构ngx_cycle_t
    cycle = ngx_init_cycle(&init_cycle);
    if (cycle == NULL) {
        if (ngx_test_config) {
            ngx_log_stderr(0, "configuration file %s test failed",
                           init_cycle.conf_file.data);
        }

        return 1;
    }

    // 若开启测试配置文件,则测试配置文件
    if (ngx_test_config) {
        if (!ngx_quiet_mode) {
            ngx_log_stderr(0, "configuration file %s test is successful",
                           cycle->conf_file.data);
        }

        if (ngx_dump_config) {
            cd = cycle->config_dump.elts;

            for (i = 0; i < cycle->config_dump.nelts; i++) {

                ngx_write_stdout("# configuration file ");
                (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
                                    cd[i].name.len);
                ngx_write_stdout(":" NGX_LINEFEED);

                b = cd[i].buffer;

                (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
                ngx_write_stdout(NGX_LINEFEED);
            }
        }

        return 0;
    }

    // 若有信号,则处理信号
    if (ngx_signal) {
        return ngx_signal_process(cycle, ngx_signal);
    }

    ngx_os_status(cycle->log);

    ngx_cycle = cycle;

    // ccf指向存储ngx_core_module配置项的数据结构
    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    /* 在ngx_core_module_create_conf()中,ccf->master初始化为-1;
       在ngx_core_module_init_conf()中,若ccf->master == -1,则ccf->master = 1,否则ccf->master不变;
       ngx_process是一个未初始化的全局变量,默认值是0(即NGX_PROCESS_SINGLE) */
    if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
        ngx_process = NGX_PROCESS_MASTER;
    }

#if !(NGX_WIN32)

    if (ngx_init_signals(cycle->log) != NGX_OK) {
        return 1;
    }

    // 若无继承socket,且设置了守护进程标识,则调用ngx_daemon()创建守护进程。
    if (!ngx_inherited && ccf->daemon) {
        if (ngx_daemon(cycle->log) != NGX_OK) {
            return 1;
        }

        ngx_daemonized = 1;
    }

    if (ngx_inherited) {
        ngx_daemonized = 1;
    }

#endif

    // 创建pid文件
    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
        return 1;
    }

    if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
        return 1;
    }

    if (log->file->fd != ngx_stderr) {
        if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          ngx_close_file_n " built-in log failed");
        }
    }

    ngx_use_stderr = 0;

    if (ngx_process == NGX_PROCESS_SINGLE) {
        // 单进程工作模式:系统中只有一个进程,该进程既是master进程,也是worker进程
        ngx_single_process_cycle(cycle);

    } else {
        // 多进程工作模式:系统中有一个master进程,多个worker进程
        ngx_master_process_cycle(cycle);
    }

    return 0;
}

原文地址:https://www.cnblogs.com/blackhumour2018/p/9427822.html

时间: 2024-10-12 18:16:46

Nginx源码阅读(main)的相关文章

菜鸟nginx源码剖析 框架篇(一) 从main函数看nginx启动流程(转)

俗话说的好,牵牛要牵牛鼻子 驾车顶牛,处理复杂的东西,只要抓住重点,才能理清脉络,不至于深陷其中,不能自拔.对复杂的nginx而言,main函数就是“牛之鼻”,只要能理清main函数,就一定能理解其中的奥秘,下面我们就一起来研究一下nginx的main函数. 1.nginx的main函数解读 nginx启动显然是由main函数驱动的,main函数在在core/nginx.c文件中,其源代码解析如下,涉及到的数据结构在本节仅指出其作用,将在第二节中详细解释. nginx main函数的流程图如下:

CI框架源码阅读笔记1 - 环境准备、基本术语和框架流程

最开始使用CI框架的时候,就打算写一个CI源码阅读的笔记系列,可惜虎头蛇尾,一直没有行动.最近项目少,总算是有了一些时间去写一些东西.于是准备将之前的一些笔记和经验记录下来,一方面权作备忘,另一方面时刻提醒自己:借鉴和学习才有出路,忘记过去意味着背叛! 基本术语说明 在本文开始之前,有必要对文中反复出现的术语做一个简单的说明,如果你对这一部分已经熟谙,完全可以略过.本文中反复出现和提及的术语包括: 前端控制器(Front Controller): 用于集中控制用户的所有请求的组件,将用户的请求发

nginx源码学习资源

http://www.cnblogs.com/yjf512/archive/2012/06/13/2548515.html 2012-06-13 21:32 by 轩脉刃, 26499 阅读, 5 评论, 收藏, 编辑 nginx源码学习是一个痛苦又快乐的过程,下面列出了一些nginx的学习资源. 首先要做的当然是下载一份nginx源码,可以从nginx官方网站下载一份最新的. 看了nginx源码,发现这是一份完全没有注释,完全没有配置文档的代码. 现在你最希望要的是一份注释版的nginx源码,

Nginx源码分析:3张图看懂启动及进程工作原理

编者按:高可用架构分享及传播在架构领域具有典型意义的文章,本文由陈科在高可用架构群分享.转载请注明来自高可用架构公众号「ArchNotes」.   导读:很多工程师及架构师都希望了解及掌握高性能服务器开发,阅读优秀源代码是一种有效的方式,nginx 是业界知名的高性能 Web 服务器实现,如何有效的阅读及理解 nginx?本文用图解的方式帮助大家来更好的阅读及理解 nginx 关键环节的实现.   陈科,十年行业从业经验,曾在浙江电信.阿里巴巴.华为.五八同城任开发工程及架构师等职,目前负责河狸

Nginx源码分析 - Nginx启动以及IOCP模型

Nginx 源码分析 - Nginx启动以及IOCP模型 版本及平台信息 本文档针对Nginx1.11.7版本,分析Windows下的相关代码,虽然服务器可能用linux更多,但是windows平台下的代码也基本相似 ,另外windows的IOCP完成端口,异步IO模型非常优秀,很值得一看. Nginx启动 曾经有朋友问我,面对一个大项目的源代码,应该从何读起呢?我给他举了一个例子,我们学校大一大二是在紫金港校区,到了 大三搬到玉泉校区,但是大一的时候也会有时候有事情要去玉泉办.偶尔会去玉泉,但

CI框架源码阅读笔记3 全局函数Common.php

从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap引导文件都会最先引入全局函数,以便于之后的处理工作). 打开Common.php中,第一行代码就非常诡异: if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 上一篇(CI框架源码阅读笔记2 一切的入口 index

nginx源码分析--进程间通信机制 &amp; 同步机制

Nginx源码分析-进程间通信机制 从nginx的进程模型可以知道,master进程和worker进程需要通信,nginx中通信的方式有套接字.共享内存.信号.对于master进程,从外部接受信号,master进程主要就是监控.接受外部信号,将有必要的信号传递给worker进程,master进程大部分时间都是阻塞在sigsuspend()函数调用上.Worker进程屏蔽了所有的外部信号,那么Master进程就通过套接字和worker进程通信,worker进程修改全局变量,使得worker进程接受

nginx源码学习(二)

上一篇文章主要介绍了nginx在win和Linux平台上的安装.本章节主要介绍nginx源码学习方法和源码结构,以及nginx启动时main方法的位置,参数信息.后面的章节主要是linux平台,你要问为何是linux,而不是win.我只能说nginx是基于linux平台开发出来的,我也习惯了linux平台开发.   上一篇文章我讲了安装,现在打开MobaXterm,连接上nginx服务器.输入whereis nginx命令查看安装目录:   是的我的安装目录在  /usr/local/nginx

【原】AFNetworking源码阅读(六)

[原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AFNetworking的网络安全策略,尤其指HTTPS(大家可以先简单了解下HTTPS).再一个就是分析下AFNetworkReachabilityManager文件,看看AFNetworking如何解决网络状态的检测. 2. AFSecurityPolicy - 网络安全策略 之前我们在AFURLS