nginx源码初读(12)--跟main一起看流程(Block 1: 初始化基础模块 Block 2:获取参数)
来源:互联网 发布:华南师范网络教育网站 编辑:程序博客网 时间:2024/06/05 15:29
在这一节终于可以开始看流程看机制了,还是小激动的,毕竟只看数据结构还是不懂。因为数据结构+算法+代码才能完整的理解nginx啊。前面11节我们总结了所有可能用到的基本数据结构,至于每个结构相应的方法,出了str其他没有过多讲述,后面看流程的时候遇到都会进行研究。
我就直接分阶段贴代码了,一段一段慢慢的看。有一些内容对理解没什么用就直接…了,见谅。
Block 1: 初始化基础模块
—->>函数启动:main
int ngx_cdecl // 在第1节里有,ngx_cdecl是一个留用的宏定义,为了解决以后可能出现的移植性问题main(int argc, char *const *argv){ ngx_int_t i; // 后面都用来做循环的index ngx_log_t *log; ngx_cycle_t *cycle, init_cycle; ngx_core_conf_t *ccf; ngx_debug_init(); // 根据NGX_DEBUG_MALLOC来设定ngx_debug_malloc参数
—->>函数调用:ngx_debug_init
void ngx_debug_init(void) { #if (NGX_DEBUG_MALLOC) // 改变或新增加环境变量(注意这里的环境变量是当前进程的,和shell无关,进程结束就没了) setenv("MallocScribble", "1", 0); ngx_debug_malloc = 1; #else // 没有定义,看系统中是否有定义MallocScribble,有的话设置ngx_debug_malloc if (getenv("MallocScribble")) { ngx_debug_malloc = 1; } #endif }
<<—-调用返回:main
// 初始化errlist列表 if (ngx_strerror_init() != NGX_OK) { return 1; }
—->>函数调用:ngx_strerror_init
ngx_int_t ngx_strerror_init(void) { char *msg; // 临时使用的指针,接收strerror返回的字符串 u_char *p; // 临时使用的指针,创建内存后获取内容并转交地址 size_t len; // 临时使用的长度 ngx_err_t err; // 错误代码 /* 申请内存空间给errlist,NGX_SYS_NERR是错误熟料 */ len = NGX_SYS_NERR * sizeof(ngx_str_t); ngx_sys_errlist = malloc(len); // ngx_errno.c定义的静态指针 if (ngx_sys_errlist == NULL) { goto failed; // 问:这里为什么使用goto不用if-else?看起来用else也不会让逻辑混乱啊。 // 答:不觉得goto很方便么,多个else放一个goto里处理。反正在功能性函数内不会乱。 } /* 使用标准库函数strerror根据错误代码返回错误原因的描述字符串,并存储到errlist中 */ for (err = 0; err < NGX_SYS_NERR; err++) { msg = strerror(err); len = ngx_strlen(msg); p = malloc(len); if (p == NULL) { goto failed; } ngx_memcpy(p, msg, len); ngx_sys_errlist[err].len = len; ngx_sys_errlist[err].data = p; } return NGX_OK; /* malloc错误统一处理,因为这时errlist还没初始化好,ngx_strerror不能用,所以使用log_error */ failed: err = errno; ngx_log_stderr(0, "malloc(%uz) failed (%d: %s)", len, err, strerror(err)); return NGX_ERROR; }
<<—-调用返回:main
Block 2: 获取参数
/* 解析命令行输入的各参数 */ if (ngx_get_options(argc, argv) != NGX_OK) { return 1; }
—->>函数调用:ngx_get_options
static ngx_int_t ngx_get_options(int argc, char *const *argv) { u_char *p; ngx_int_t i; /* 循环解析参数,跟之前一篇博文使用标准解析函数的方法不一样,这样解析更加灵活 * argv[0]是程序执行路径,不解析 */ for (i = 1; i < argc; i++) { /* 指针位置就是p[0]位置,直接解析字符,如果不是-说明参数格式错误 */ p = (u_char *) argv[i]; if (*p++ != '-') { ngx_log_stderr(0, "invalid option: \"%s\"", argv[i]); return NGX_ERROR; } /* 发现'-'后p++已经指向对应的参数(加减单位是sizeof(u_char)),进行解析设置相应参数 */ while (*p) { switch (*p++) { case '?': case 'h': ngx_show_version = 1; // 用于显示version信息 ngx_show_help = 1; // 用于显示help信息 break; case 'v': ngx_show_version = 1; break; case 'V': ngx_show_version = 1; ngx_show_configure = 1; // 用于显示配置信息 break; case 't': ngx_test_config = 1; // 检测配置文件 break; case 'q': ngx_quiet_mode = 1; // -t的参数 break; case 'p': // 设置prefix路径 if (*p) { ngx_prefix = p; goto next; } if (argv[++i]) { ngx_prefix = (u_char *) argv[i]; goto next; } ngx_log_stderr(0, "option \"-p\" requires directory name"); return NGX_ERROR; case 'c': // 设置配置文件 /* 参数直接跟在p后面"-p/home/tut/..." */ if (*p) { ngx_conf_file = p; goto next; } /* 参数在下一个argv */ if (argv[++i]) { ngx_conf_file = (u_char *) argv[i]; goto next; } ngx_log_stderr(0, "option \"-c\" requires file name"); return NGX_ERROR; case 'g': if (*p) { ngx_conf_params = p; // 全局配置文件输出文件夹 goto next; } if (argv[++i]) { ngx_conf_params = (u_char *) argv[i]; goto next; } ngx_log_stderr(0, "option \"-g\" requires parameter"); return NGX_ERROR; case 's': /* 在没错的情况下有后续操作,所以没用goto用了if-else */ if (*p) { ngx_signal = (char *) p; } else if (argv[++i]) { ngx_signal = argv[i]; } else { ngx_log_stderr(0, "option \"-s\" requires parameter"); return NGX_ERROR; } /* 这几种信号都在signaller进程中处理了到时候,其他信号不处理 */ if (ngx_strcmp(ngx_signal, "stop") == 0 || ngx_strcmp(ngx_signal, "quit") == 0 || ngx_strcmp(ngx_signal, "reopen") == 0 || ngx_strcmp(ngx_signal, "reload") == 0) { ngx_process = NGX_PROCESS_SIGNALLER; goto next; } ngx_log_stderr(0, "invalid option: \"-s %s\"", ngx_signal); return NGX_ERROR; default: ngx_log_stderr(0, "invalid option: \"%c\"", *(p - 1)); return NGX_ERROR; } } next: continue; } return NGX_OK; }
—-<<调用返回:main
if (ngx_show_version) { /* ngx_write_stderr -> ngx_write_fd(ngx_stderr(宏定义标准错误输出),...) -> write(fd,...) */ ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED); if (ngx_show_help) { ngx_write_stderr("输出使用说明,篇幅太长,省略,感兴趣的直接源码或者-h"); } if (ngx_show_configure) {/* 输出各种配置信息 */} if (!ngx_test_config) { // 没啥事了(不需要检测config),可以退出了 return 0; } }
Block 1:初始化基础模块
/* TODO */ ngx_max_sockets = -1; ngx_time_init(); // 初始化系统时间
—->>函数调用:ngx_time_init
void ngx_time_init(void) { ngx_cached_err_log_time.len = sizeof("1970/09/28 12:00:00") - 1; ngx_cached_http_time.len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1; ngx_cached_http_log_time.len = sizeof("28/Sep/1970:12:00:00 +0600") - 1; ngx_cached_http_log_iso8601.len = sizeof("1970-09-28T12:00:00+06:00") - 1; ngx_cached_syslog_time.len = sizeof("Sep 28 12:00:00") - 1; /* static ngx_time_t cached_time[NGX_TIME_SLOTS];*/ ngx_cached_time = &cached_time[0]; ngx_time_update(); // 更新系统时间 }
—->>函数调用:ngx_time_update
0 0
- nginx源码初读(12)--跟main一起看流程(Block 1: 初始化基础模块 Block 2:获取参数)
- 菜鸟nginx源码剖析 框架篇(一) 从main函数看nginx启动流程
- 菜鸟nginx源码剖析 框架篇(一) 从main函数看nginx启动流程
- nginx源码剖析 从main函数看nginx启动流程
- Block 讲解(基础)
- Aspects源码解读:动态Block调用(不定参数的Block)
- oracle block internal(block 内部结构分解)[要看]
- Block介绍(一)基础
- Block介绍(一)基础
- Block介绍(一)基础
- Block介绍(一)基础
- Block介绍(一)基础
- Block介绍(一)基础
- Block介绍(一)基础
- block(2)
- moodle 板块(block)开发流程小记
- django模板继承常用标签和规则(看django源码遇到了{{ block.super }})
- 详细解释:nginx中Nginx Main Module(主模块)配置及各个参数含义
- 2016年第2次吐槽小米,系统升级连不上wifi
- android studio导入Eclipse遇到的问题一
- 十大 HTML 5 前端框架
- “懒”出效率是程序员的美德
- java-memory-model
- nginx源码初读(12)--跟main一起看流程(Block 1: 初始化基础模块 Block 2:获取参数)
- varnish指南
- swift中的扩展
- 关于Cavans的细致分析
- 最短路径(一)——多源最短路径
- JS window.open()属性
- bit、byte、位、字节、汉字、字符之间的区别
- Varnish Configuration Language - VCL(varnish配置语言-VCL)
- 如何制作macbook系统u盘安装盘