nginx main流程分析

2024-08-24 16:18
文章标签 分析 流程 nginx main

本文主要是介绍nginx main流程分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!



int ngx_cdecl
main(int argc, char *const * argv)
{
ngx_int_t         i;
ngx_log_t        * log;
ngx_cycle_t      * cycle, init_cycle ;
ngx_core_conf_t  * ccf;
/*
第一个函数ngx_debug_init(),这个函数主要是作为初始化debug用的,nginx中的debug,主要是对内存池分配管理方面的debug,因为作为一个应用程序,最容易出现bug的地方也是内存管理这块。在Linux版本中,这个函数只是一个空定义(src/os/unix/ngx_linux_config.h)。
#define ngx_debug_init()
*/
ngx_debug_init();
/*
*我们来到程序的第208行,ngx_strerror_init(),该函数的定义在文件src/os/unix/ngx_errno.c中。
*该函数主要初始化系统中错误编号对应的含义,这样初始化中进行对应的好处是,当出现错误,
*不用再去调用strerror()函数来获取错误原因,而直接可以根据错误编号找到对应的错误原因,
*可以提高运行时的执行效率。从这里可以看到,nginx开发者的别有用心,对于微小的性能提升也毫不放过。 */
if (ngx_strerror_init() != NGX_OK) {
return 1;
}
//获得运行时选项
if (ngx_get_options( argc, argv ) != NGX_OK) {
return 1;
}
if (ngx_show_version) {
ngx_write_stderr( "nginx version: " NGINX_VER NGX_LINEFEED );
if (ngx_show_help) {
ngx_write_stderr(
"Usage: nginx [-?hvVtq] [-s signal] [-c filename] "
"[-p prefix] [-g directives]" NGX_LINEFEED
NGX_LINEFEED
"Options:" NGX_LINEFEED
"  -?,-h         : this help" NGX_LINEFEED
"  -v            : show version and exit" NGX_LINEFEED
"  -V            : show version and configure options then exit"
NGX_LINEFEED
"  -t            : test configuration and exit" NGX_LINEFEED
"  -q            : suppress non-error messages "
"during configuration testing" NGX_LINEFEED
"  -s signal     : send signal to a master process: "
"stop, quit, reopen, reload" NGX_LINEFEED
#ifdef NGX_PREFIX
"  -p prefix     : set prefix path (default: "
NGX_PREFIX ")" NGX_LINEFEED
#else
"  -p prefix     : set prefix path (default: NONE)" NGX_LINEFEED
#endif
"  -c filename   : set configuration file (default: "
NGX_CONF_PATH ")" NGX_LINEFEED
"  -g directives : set global directives out of configuration "
"file" NGX_LINEFEED NGX_LINEFEED
);
}
if (ngx_show_configure) {
ngx_write_stderr(
#ifdef NGX_COMPILER
"built by " NGX_COMPILER NGX_LINEFEED
#endif
#if (NGX_SSL)
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
"TLS SNI support enabled" NGX_LINEFEED
#else
"TLS SNI support disabled" NGX_LINEFEED
#endif
#endif
"configure arguments:" NGX_CONFIGURE NGX_LINEFEED);
}
if (!ngx_test_config) {
return 0;
}
}
/* TODO */ ngx_max_sockets = -1;
//初始化系统时间
ngx_time_init();
#if (NGX_PCRE)
ngx_regex_init();
#endif
ngx_pid = ngx_getpid();
//初始化日志信息
log = ngx_log_init(ngx_prefix);
if (log == NULL) {
return 1;
}
/* STUB */
#if (NGX_OPENSSL)
ngx_ssl_init( log);
#endif
/*
* init_cycle->log is required for signal handlers and
* ngx_process_options()
*/
/*
ngx_string.h 第86行
#define ngx_memzero(buf, n)       (void) memset(buf, 0, n)
ngx_cycle_s 机构体:ngx_cycle.h 第37行
*/
ngx_memzero(& init_cycle, sizeof (ngx_cycle_t));
//开始初始化ngx_cycle_s *init_cycle对象
init_cycle. log = log ;
ngx_cycle = & init_cycle;
// 为ngx_cycle 创建内存池 ,ngx_pool我们在另一篇博客中再讲
init_cycle. pool = ngx_create_pool(1024, log );
if (init_cycle. pool == NULL ) {
return 1;
}
// 保存进程参数到init_cycle中
if (ngx_save_argv(& init_cycle, argc , argv) != NGX_OK) {
return 1;
}
// 处理进程参数
if (ngx_process_options(& init_cycle) != NGX_OK) {
return 1;
}
// 获取系统配置信息 (分页大小,CPU 个数,CPU 制造商,文件符最大数等)  
if (ngx_os_init( log) != NGX_OK) {
return 1;
}
/*
* ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
*/
// 初始化循环冗余检验表,验证接收数据
if (ngx_crc32_table_init() != NGX_OK) {
return 1;
}
//通过环境变量NGINX完成socket的继承,这些继承来的socket会放到init_cycyle的listening数组中。
if (ngx_add_inherited_sockets(& init_cycle) != NGX_OK) {
return 1;
}
ngx_max_module = 0;
/**
* nginx把所有模块(ngx_module_t)存放到ngx_modules数组中,这个数组在nginx源码路
* 径的objs/ngx_modules.c中,是在运行configure脚本后生成的。index属性就是该模块
* 在ngx_modules数组中的下标。同时nginx把所有的core module的配置结构存放到ngx_cycle的
* conf_ctx数组中,index也是该模块的配置结构在ngx_cycle->conf_ctx数组中的下标。
**/
for (i = 0; ngx_modules[ i]; i ++) {
ngx_modules[ i]->index = ngx_max_module++;
}
// 初始化init cycle 变量,这是个牛逼的结构 
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);
}
return 0;
}
if (ngx_signal) {
return ngx_signal_process(cycle , ngx_signal);
}
ngx_os_status( cycle->log );
ngx_cycle = cycle;
// 获取core module 的配置指针  
ccf = (ngx_core_conf_t *) ngx_get_conf( cycle->conf_ctx , ngx_core_module);
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;
}
if (!ngx_inherited && ccf->daemon) {
if (ngx_daemon(cycle ->log) != NGX_OK) {
return 1;
}
ngx_daemonized = 1;
}
if (ngx_inherited) {
ngx_daemonized = 1;
}
#endif
if (ngx_create_pidfile(& ccf->pid , cycle-> log) != NGX_OK) {
return 1;
}
if (cycle-> log->file ->fd != ngx_stderr) {
if (ngx_set_stderr(cycle ->log-> file->fd ) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_EMERG, cycle->log , ngx_errno,
ngx_set_stderr_n " failed");
return 1;
}
}
//检查log文件句柄
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) {
ngx_single_process_cycle( cycle);
} else {
ngx_master_process_cycle( cycle);
}
return 0;
}


这篇关于nginx main流程分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1102976

相关文章

Nginx安全防护的多种方法

《Nginx安全防护的多种方法》在生产环境中,需要隐藏Nginx的版本号,以避免泄漏Nginx的版本,使攻击者不能针对特定版本进行攻击,下面就来介绍一下Nginx安全防护的方法,感兴趣的可以了解一下... 目录核心安全配置1.编译安装 Nginx2.隐藏版本号3.限制危险请求方法4.请求限制(CC攻击防御)

nginx中端口无权限的问题解决

《nginx中端口无权限的问题解决》当Nginx日志报错bind()to80failed(13:Permissiondenied)时,这通常是由于权限不足导致Nginx无法绑定到80端口,下面就来... 目录一、问题原因分析二、解决方案1. 以 root 权限运行 Nginx(不推荐)2. 为 Nginx

SpringBoot中六种批量更新Mysql的方式效率对比分析

《SpringBoot中六种批量更新Mysql的方式效率对比分析》文章比较了MySQL大数据量批量更新的多种方法,指出REPLACEINTO和ONDUPLICATEKEY效率最高但存在数据风险,MyB... 目录效率比较测试结构数据库初始化测试数据批量修改方案第一种 for第二种 case when第三种

解决1093 - You can‘t specify target table报错问题及原因分析

《解决1093-Youcan‘tspecifytargettable报错问题及原因分析》MySQL1093错误因UPDATE/DELETE语句的FROM子句直接引用目标表或嵌套子查询导致,... 目录报js错原因分析具体原因解决办法方法一:使用临时表方法二:使用JOIN方法三:使用EXISTS示例总结报错原

Ubuntu 24.04启用root图形登录的操作流程

《Ubuntu24.04启用root图形登录的操作流程》Ubuntu默认禁用root账户的图形与SSH登录,这是为了安全,但在某些场景你可能需要直接用root登录GNOME桌面,本文以Ubuntu2... 目录一、前言二、准备工作三、设置 root 密码四、启用图形界面 root 登录1. 修改 GDM 配

nginx 负载均衡配置及如何解决重复登录问题

《nginx负载均衡配置及如何解决重复登录问题》文章详解Nginx源码安装与Docker部署,介绍四层/七层代理区别及负载均衡策略,通过ip_hash解决重复登录问题,对nginx负载均衡配置及如何... 目录一:源码安装:1.配置编译参数2.编译3.编译安装 二,四层代理和七层代理区别1.二者混合使用举例

nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析(结合应用场景)

《nginx-t、nginx-sstop和nginx-sreload命令的详细解析(结合应用场景)》本文解析Nginx的-t、-sstop、-sreload命令,分别用于配置语法检... 以下是关于 nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析,结合实际应

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.