Ubuntu-下-nginx-1.24.0-源码分析-1
目录
Ubuntu 下 nginx-1.24.0 源码分析 (1)
main 函数在
src\core\nginx.c
int ngx_cdecl
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();
进入 main 函数
最开始是局部变量的声明
然后是
接下来是 :
if (ngx_strerror_init() != NGX_OK) {
return 1;
}
接下来是 :
if (ngx_get_options(argc, argv) != NGX_OK) {
return 1;
}
当前这次执行的是:
sudo ./nginx
除了 程序名 没有其他参数
所以
argc=1
于是在 ngx_get_options 函数中
static ngx_int_t
ngx_get_options(int argc, char *const *argv)
{
u_char *p;
ngx_int_t i;
for (i = 1; i < argc; i++) {
p = (u_char *) argv[i];
if (*p++ != '-') {
ngx_log_stderr(0, "invalid option: \"%s\"", argv[i]);
return NGX_ERROR;
}
while (*p) {
switch (*p++) {
case '?':
case 'h':
ngx_show_version = 1;
ngx_show_help = 1;
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 'T':
ngx_test_config = 1;
ngx_dump_config = 1;
break;
case 'q':
ngx_quiet_mode = 1;
break;
case 'p':
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 'e':
if (*p) {
ngx_error_log = p;
} else if (argv[++i]) {
ngx_error_log = (u_char *) argv[i];
} else {
ngx_log_stderr(0, "option \"-e\" requires file name");
return NGX_ERROR;
}
if (ngx_strcmp(ngx_error_log, "stderr") == 0) {
ngx_error_log = (u_char *) "";
}
goto next;
case 'c':
if (*p) {
ngx_conf_file = p;
goto next;
}
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':
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;
}
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;
}
进入不了 for 循环
直接走到
return NGX_OK;
返回到 main 函数中
接下来是 :
if (ngx_show_version) {
ngx_show_version_info();
if (!ngx_test_config) {
return 0;
}
}
ngx_show_version 未设置,此时是 0
于是跳过这段代码
接下来是 :
/* TODO */ ngx_max_sockets = -1;
初始化全局变量 ngx_max_sockets
ngx_max_sockets
是一个全局变量,用于存储 Nginx 能够处理的最大文件描述符(socket)数量。
文件描述符 是操作系统用于管理打开的文件、socket 等资源的标识符。Nginx 作为一个高性能的 Web 服务器,需要处理大量的并发连接,因此文件描述符的数量对性能有重要影响
初始值为 -1
的意义
将
ngx_max_sockets
初始化为-1
表示在程序启动时,还没有确定实际的最大文件描述符数量。-1
通常用作一个初始值或无效值,表示该变量 尚未被正确初始化或配置 。在后续的代码中,Nginx 会根据操作系统的限制和配置文件中的设置来更新
ngx_max_sockets
的值。
接下来是 :
ngx_time_init();
接下来是 :
#if (NGX_PCRE)
ngx_regex_init();
#endif
接下来是 :
ngx_pid = ngx_getpid();
ngx_parent = ngx_getppid();
获取当前进程的进程ID( ngx_pid
)和父进程的进程ID( ngx_parent
)。
这在后续的进程管理中很有用。
在 src/os/unix/ngx_process.h 中:
#define ngx_getpid getpid
#define ngx_getppid getppid
getpid
和getppid
是 C 语言中用于获取进程 ID 的函数,定义在<unistd.h>
头文件中getpid():获取当前进程的进程ID getppid():获取当前进程的父进程ID
父进程是创建当前进程的进程(如通过fork())。 若父进程终止,子进程的PPID会被重置为init进程(PID=1)
接下来是:
log = ngx_log_init(ngx_prefix, ngx_error_log);
if (log == NULL) {
return 1;
}
此次调用 ngx_log_init 时
prefix 和 error_log 都还没有设置此时还是 null
进入 ngx_log_init
首先是
ngx_log_t *
ngx_log_init(u_char *prefix, u_char *error_log)
{
u_char *p, *name;
size_t nlen, plen;
ngx_log.file = &ngx_log_file;
ngx_log.log_level = NGX_LOG_NOTICE;
将全局日志对象
ngx_log
的文件指针指向ngx_log_file
。设置默认日志级别为
NGX_LOG_NOTICE
(通知级别)
if (error_log == NULL) {
error_log = (u_char *) NGX_ERROR_LOG_PATH;
}
name = error_log;
nlen = ngx_strlen(name);
此时 error_log 还是null
于是进入这个 if 条件中
把默认值 NGX_ERROR_LOG_PATH 赋值给 error_log
这个默认值是在 执行 configure 命令时定义的一个宏,它的值由 configure 命令的配置项 –error-log-path 指定
if (nlen == 0) {
ngx_log_file.fd = ngx_stderr;
return &ngx_log;
}
p = NULL;
nlen 不是0
跳过这个 if 条件
if (name[0] != '/') {
检查路径是否以 /
开头
是以 /
开头
所以当前 name 已经是绝对路径了,不需要拼接前缀
ngx_log_file.fd = ngx_open_file(name, NGX_FILE_APPEND,
NGX_FILE_CREATE_OR_OPEN,
NGX_FILE_DEFAULT_ACCESS);
以追加的方式打开 name 指向的 日志文件
此时返回的 fd 是 4
if (ngx_log_file.fd == NGX_INVALID_FILE) {
ngx_log_stderr(ngx_errno,
"[alert] could not open error log file: "
ngx_open_file_n " \"%s\" failed", name);
NGX_INVALID_FILE 的值是 -1 无效的文件描述符,表示上一步的打开文件失败
现在这个条件不成立,跳过这段代码
if (p) {
ngx_free(p);
}
return &ngx_log;
由于之前条件不成立,所以 没有用到 p
最后返回 ngx_log 的地址
回到 main 函数中
接下来是:
ngx_ssl_init(log);
接下来是:
ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
把 init_cycle 的每个字节都初始化为 0
init_cycle.log = log;
将之前 初始化的 日志对象的地址 记录在 log 字段
ngx_cycle = &init_cycle;
现在 ngx_cycle 是指向 init_cycle 的指针了
init_cycle.pool = ngx_create_pool(1024, log);
创建一个内存池要求的内存大小是 1024 字节,然后将地址记录到 init_cycle 的 pool 字段进行管理
进入 ngx_create_pool
ngx_pool_t *
ngx_create_pool(size_t size, ngx_log_t *log)
{
ngx_pool_t *p;
p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log);
if (p == NULL) {
return NULL;
}
使用 ngx_memalign 来分配内存
NGX_POOL_ALIGNMENT 是要求的对齐边界,值为 16
进入 ngx_memalign
void *
ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
{
void *p;
int err;
err = posix_memalign(&p, alignment, size);
调用 posix_memalign 来分配一块对齐的内存
此次返回值为 0
也就是分配内存成功了
p=0x5aa55f9765a0
这个地址是按 16 对齐的
if (err) {
ngx_log_error(NGX_LOG_EMERG, log, err,
"posix_memalign(%uz, %uz) failed", alignment, size);
p = NULL;
}
条件不成立,跳过这段代码
return p;
把分配的地址返回到
ngx_create_pool 函数中
回到 ngx_create_pool
接下来是:
if (p == NULL) {
return NULL;
}
条件不成立,跳过这段代码
p->d.last = (u_char *) p + sizeof(ngx_pool_t);
p->d.end = (u_char *) p + size;
p->d.next = NULL;
p->d.failed = 0;
size = size - sizeof(ngx_pool_t);
p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;
p->current = p;
p->chain = NULL;
p->large = NULL;
p->cleanup = NULL;
p->log = log;
return p;
赋值然后返回 内存池 地址
当前 size = 944 , NGX_MAX_ALLOC_FROM_POOL = -1 所以 p->max=944
回到 main 函数中
接下来是:
if (init_cycle.pool == NULL) {
return 1;
}
条件不成立,跳过这段代码
if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
return 1;
}
if (ngx_process_options(&init_cycle) != NGX_OK) {
return 1;
}
进入 ngx_process_options
static ngx_int_t
ngx_process_options(ngx_cycle_t *cycle)
{
u_char *p;
size_t len;
if (ngx_prefix) {
ngx_prefix 还是 null
所以跳过这个 if 代码段进入 else
接下来是:
ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX);
将 默认的配置文件路径前缀设置给 cycle->conf_prefix
ngx_str_set(&cycle->prefix, NGX_PREFIX);
将 默认的路径前缀设置给 cycle->prefix
if (ngx_conf_file) {
cycle->conf_file.len = ngx_strlen(ngx_conf_file);
cycle->conf_file.data = ngx_conf_file;
} else {
ngx_str_set(&cycle->conf_file, NGX_CONF_PATH);
}
此次启动没有指定 配置文件路径
所以 ngx_conf_file 在这里还是 null
进入 else 中,将 默认的配置文件路径设置给 cycle->conf_file 进行管理
接下来是:
if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
return NGX_ERROR;
}
cycle->conf_file 保存的配置文件路径可能是 相对路径,需要 调用 ngx_conf_full_name 来拼接路径前缀 然后形成完成的路径
进入 ngx_conf_full_name 中
ngx_int_t
ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix)
{
ngx_str_t *prefix;
prefix = conf_prefix ? &cycle->conf_prefix : &cycle->prefix;
return ngx_get_full_name(cycle->pool, prefix, name);
}
这里传进来的 conf_prefix 的值是 0
所以 prefix = &cycle->prefix; 选择 cycle->prefix (/usr/local/nginx/) 作为配置文件路径前缀
然后调用 ngx_get_full_name 来拼接路径
进入 ngx_get_full_name
ngx_int_t
ngx_get_full_name(ngx_pool_t *pool, ngx_str_t *prefix, ngx_str_t *name)
{
size_t len;
u_char *p, *n;
ngx_int_t rc;
rc = ngx_test_full_name(name);
if (rc == NGX_OK) {
return rc;
}
调用 ngx_test_full_name 来判断 name (/home/wsd/桌面/nginx/conf/nginx.conf) 是否是完整的路径
进入 ngx_test_full_name
static ngx_int_t
ngx_test_full_name(ngx_str_t *name)
{
#if (NGX_WIN32)
u_char c0, c1;
c0 = name->data[0];
if (name->len < 2) {
if (c0 == '/') {
return 2;
}
return NGX_DECLINED;
}
c1 = name->data[1];
if (c1 == ':') {
c0 |= 0x20;
if ((c0 >= 'a' && c0 <= 'z')) {
return NGX_OK;
}
return NGX_DECLINED;
}
if (c1 == '/') {
return NGX_OK;
}
if (c0 == '/') {
return 2;
}
return NGX_DECLINED;
#else
if (name->data[0] == '/') {
return NGX_OK;
}
return NGX_DECLINED;
#endif
}
当前环境是 Ubuntu #if (NGX_WIN32) 不成立
所以接下来执行的是:
if (name->data[0] == '/') {
return NGX_OK;
}
return NGX_DECLINED;
条件成立 name 的第一个字符是 /
被认为是 绝对路径
返回 NGX_OK
回到 ngx_get_full_name
rc = ngx_test_full_name(name);
if (rc == NGX_OK) {
return rc;
}
rc 得到的返回值是 NGX_OK
条件成立,把这个 NGX_OK 返回到 ngx_conf_full_name
return ngx_get_full_name(cycle->pool, prefix, name);
这个结果继续向上返回到 ngx_process_options
回到 ngx_process_options
接下来是:
if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
return NGX_ERROR;
}
于是 这里 调用 ngx_conf_full_name 得到 返回值 NGX_OK
条件不成立
接下来是:
for (p = cycle->conf_file.data + cycle->conf_file.len - 1;
p > cycle->conf_file.data;
p--)
{
if (ngx_path_separator(*p)) {
cycle->conf_prefix.len = p - cycle->conf_file.data + 1;
cycle->conf_prefix.data = cycle->conf_file.data;
break;
}
}
cycle->conf_file.data 是配置文件路径,
cycle->conf_file.data + cycle->conf_file.len - 1 指向这个路径字符串的最后一个字节
从最后一个字符向第一个字符遍历
if (ngx_path_separator(*p)) { 判断当前这个字符是否是分隔符 /
这个 分隔符后面是 配置文件的文件名,前面是配置文件的目录
将 cycle->conf_file.data 的地址赋给 cycle->conf_prefix.data
从这个地址开始 len 个字符是 配置文件所在的目录
于是
cycle->conf_file.data(0x5bfbfeaf3e50) = cycle->conf_prefix.data(0x5bfbfeaf3e50)
这2个地址一样
cycle->conf_file.len=38 cycle->conf_file.data=/home/wsd/桌面/nginx/conf/nginx.conf cycle->conf_prefix.len=28 cycle->conf_prefix.data=/home/wsd/桌面/nginx/conf/
就是 cycle->conf_file.data 的前 28 个字节
接下来是:
if (ngx_error_log) {
cycle->error_log.len = ngx_strlen(ngx_error_log);
cycle->error_log.data = ngx_error_log;
} else {
ngx_str_set(&cycle->error_log, NGX_ERROR_LOG_PATH);
}
当前 ngx_error_log=null 还没有设置它
所以进入 else
把 默认值 NGX_ERROR_LOG_PATH(/home/wsd/桌面/nginx/LOG/error.log)
设置给 cycle->error_log
接下来是:
if (ngx_conf_params) {
cycle->conf_param.len = ngx_strlen(ngx_conf_params);
cycle->conf_param.data = ngx_conf_params;
}
ngx_conf_params 没有设置是 null
所以跳过这段代码
if (ngx_test_config) {
cycle->log->log_level = NGX_LOG_INFO;
}
ngx_test_config 是 0
所以跳过这段代码
return NGX_OK;
返回结果
回到 main 函数中
接下来是:
if (ngx_os_init(log) != NGX_OK) {
return 1;
}
进入 ngx_os_init
ngx_int_t
ngx_os_init(ngx_log_t *log)
{
ngx_time_t *tp;
ngx_uint_t n;
#if (NGX_HAVE_LEVEL1_DCACHE_LINESIZE)
long size;
#endif
#if (NGX_HAVE_OS_SPECIFIC_INIT)
if (ngx_os_specific_init(log) != NGX_OK) {
return NGX_ERROR;
}
#endif
调用 ngx_os_specific_init 函数
进入 ngx_os_specific_init
ngx_int_t
ngx_os_specific_init(ngx_log_t *log)
{
struct utsname u;
if (uname(&u) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "uname() failed");
return NGX_ERROR;
}
调用 uname 获取系统信息
这次获得的系统信息如下:
// 操作系统名称
u.sysname=Linux
//主机名 u.nodename=wsd-vm
//操作系统发行版本 u.release=6.8.0-52-generic
// 操作系统版本信息 u.version=#53~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Wed Jan 15 19:18:46 UTC 2
// 硬件架构 u.machine=x86_64
接下来是:
(void) ngx_cpystrn(ngx_linux_kern_ostype, (u_char *) u.sysname,
sizeof(ngx_linux_kern_ostype));
(void) ngx_cpystrn(ngx_linux_kern_osrelease, (u_char *) u.release,
sizeof(ngx_linux_kern_osrelease));
复制 u.sysname 和 u.release 存储到全局变量 ngx_linux_kern_ostype 和 ngx_linux_kern_osrelease
ngx_os_io = ngx_linux_io;
return NGX_OK;
设置 ngx_os_io
然后返回结果
回到 ngx_os_init
接下来是:
if (ngx_init_setproctitle(log) != NGX_OK) {
return NGX_ERROR;
}
调用 ngx_init_setproctitle
进入 ngx_init_setproctitle
ngx_int_t
ngx_init_setproctitle(ngx_log_t *log)
{
u_char *p;
size_t size;
ngx_uint_t i;
size = 0;
for (i = 0; environ[i]; i++) {
size += ngx_strlen(environ[i]) + 1;
}
遍历 环境变量
ngx_strlen(environ[i]) + 1;
是当前这个环境变量占用的内存字节数量(字符串长度 + 字符串结束标志 ‘\0’)
累加到 size 中,最终 size 的值是整个环境变量占据的字节数量
这次的执行情况:
i=0 environ[0]=“COLORTERM=truecolor” ngx_strlen(environ[0]) + 1 =20 size=20
i=1 environ[1]=“LANGUAGE=zh_CN:en” ngx_strlen(environ[1]) + 1 =18 size=38
i=2 environ[2]=“LC_ADDRESS=zh_CN.UTF-8” ngx_strlen(environ[2]) + 1 =23 size=61
i=3 environ[3]=“LC_NAME=zh_CN.UTF-8” ngx_strlen(environ[3]) + 1 =20 size=81
i=4 environ[4]=“LC_MONETARY=zh_CN.UTF-8” ngx_strlen(environ[4]) + 1 =24 size=105
i=5 environ[5]=“XAUTHORITY=/run/user/1000/.mutter-Xwaylandauth.SUZ122” ngx_strlen(environ[5]) + 1 =54 size=159
i=6 environ[6]=“LC_PAPER=zh_CN.UTF-8” ngx_strlen(environ[6]) + 1 =21 size=180
i=7 environ[7]=“LANG=zh_CN.UTF-8” ngx_strlen(environ[7]) + 1 =17 size=197
i=8 environ[8]=“LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:.tar=01;31:.tgz=01;31:.arc=01;31:.arj=01;31:.taz=01;31:.lha=01;31:.lz4=01;31:.lzh=01;31:.lzma=01;31:.tlz=01;31:.txz=01;31:.tzo=01;31:.t7z=01;31:.zip=01;31:.z=01;31:.dz=01;31:.gz=01;31:.lrz=01;31:.lz=01;31:.lzo=01;31:.xz=01;31:.zst=01;31:.tzst=01;31:.bz2=01;31:.bz=01;31:.tbz=01;31:.tbz2=01;31:.tz=01;31:.deb=01;31:.rpm=01;31:.jar=01;31:.war=01;31:.ear=01;31:.sar=01;31:.rar=01;31:.alz=01;31:.ace=01;31:.zoo=01;31:.cpio=01;31:.7z=01;31:.rz=01;31:.cab=01;31:.wim=01;31:.swm=01;31:.dwm=01;31:.esd=01;31:.jpg=01;35:.jpeg=01;35:.mjpg=01;35:.mjpeg=01;35:.gif=01;35:.bmp=01;35:.pbm=01;35:.pgm=01;35:.ppm=01;35:.tga=01;35:.xbm=01;35:.xpm=01;35:.tif=01;35:.tiff=01;35:.png=01;35:.svg=01;35:.svgz=01;35:.mng=01;35:.pcx=01;35:.mov=01;35:.mpg=01;35:.mpeg=01;35:.m2v=01;35:.mkv=01;35:.webm=01;35:.webp=01;35:.ogm=01;35:.mp4=01;35:.m4v=01;35:.mp4v=01;35:.vob=01;35:.qt=01;35:.nuv=01;35:.wmv=01;35:.asf=01;35:.rm=01;35:.rmvb=01;35:.flc=01;35:.avi=01;35:.fli=01;35:.flv=01;35:.gl=01;35:.dl=01;35:.xcf=01;35:.xwd=01;35:.yuv=01;35:.cgm=01;35:.emf=01;35:.ogv=01;35:.ogx=01;35:.aac=00;36:.au=00;36:.flac=00;36:.m4a=00;36:.mid=00;36:.midi=00;36:.mka=00;36:.mp3=00;36:.mpc=00;36:.ogg=00;36:.ra=00;36:.wav=00;36:.oga=00;36:.opus=00;36:.spx=00;36:.xspf=00;36:” ngx_strlen(environ[8]) + 1 =1519 size=1716
i=9 environ[9]=“XDG_CURRENT_DESKTOP=ubuntu:GNOME” ngx_strlen(environ[9]) + 1 =33 size=1749
i=10 environ[10]=“TERM=xterm-256color” ngx_strlen(environ[10]) + 1 =20 size=1769
i=11 environ[11]=“LC_IDENTIFICATION=zh_CN.UTF-8” ngx_strlen(environ[11]) + 1 =30 size=1799
i=12 environ[12]=“DISPLAY=:0” ngx_strlen(environ[12]) + 1 =11 size=1810
i=13 environ[13]=“LC_TELEPHONE=zh_CN.UTF-8” ngx_strlen(environ[13]) + 1 =25 size=1835
i=14 environ[14]=“LC_MEASUREMENT=zh_CN.UTF-8” ngx_strlen(environ[14]) + 1 =27 size=1862
i=15 environ[15]=“LC_TIME=zh_CN.UTF-8” ngx_strlen(environ[15]) + 1 =20 size=1882
i=16 environ[16]=“PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin” ngx_strlen(environ[16]) + 1 =76 size=1958
i=17 environ[17]=“LC_NUMERIC=zh_CN.UTF-8” ngx_strlen(environ[17]) + 1 =23 size=1981
i=18 environ[18]=“MAIL=/var/mail/root” ngx_strlen(environ[18]) + 1 =20 size=2001
i=19 environ[19]=“LOGNAME=root” ngx_strlen(environ[19]) + 1 =13 size=2014
i=20 environ[20]=“USER=root” ngx_strlen(environ[20]) + 1 =10 size=2024
i=21 environ[21]=“HOME=/root” ngx_strlen(environ[21]) + 1 =11 size=2035
i=22 environ[22]=“SHELL=/bin/bash” ngx_strlen(environ[22]) + 1 =16 size=2051
i=23 environ[23]=“SUDO_COMMAND=./nginx” ngx_strlen(environ[23]) + 1 =21 size=2072
i=24 environ[24]=“SUDO_USER=wsd” ngx_strlen(environ[24]) + 1 =14 size=2086
i=25 environ[25]=“SUDO_UID=1000” ngx_strlen(environ[25]) + 1 =14 size=2100
i=26 environ[26]=“SUDO_GID=1000” ngx_strlen(environ[26]) + 1 =14 size=2114
接下来是:
p = ngx_alloc(size, log);
if (p == NULL) {
return NGX_ERROR;
}
为环境变量分配内存,环境变量将要迁移到新分配的内存中
此次运行的情况:
p = ngx_alloc(size=2114, log);
p=0x654273b10f20
接下来是:
ngx_os_argv_last = ngx_os_argv[0];
ngx_os_argv_last
将用于标记命令行参数可用的边界
ngx_os_argv[0]
是存储参数的那片内存的首地址
接下来是:
for (i = 0; ngx_os_argv[i]; i++) {
if (ngx_os_argv_last == ngx_os_argv[i]) {
ngx_os_argv_last = ngx_os_argv[i] + ngx_strlen(ngx_os_argv[i]) + 1;
}
}
循环,每次循环获取下一个参数的首地址,直到这个地址为 null ,
null 是标记,意味着到此为止,后面没有更多的参数了
ngx_os_argv[i] 是参数首地址, ngx_strlen(ngx_os_argv[i]) 是参数的长度,最后再 + 1 ,就越过了这个参数的最后一个字节成了下一个参数的最后一个字节
所以下一次循环时 ngx_os_argv[i] 是下一个参数的首地址 等于 上一次循环被重新赋值的 ngx_os_argv_last
这样 ngx_os_argv_last
的值在不断的向后移动,直到它等于存贮参数的内存的最后一个字节的下一个字节(也是环境变量的第一个字节)
此次的执行情况是:
i=0 ngx_os_argv_last(0x7ffecc4747a6) == ngx_os_argv ngx_os_argv_last(0x7ffecc4747ae) = ngx_os_argv[0] + ngx_strlen(ngx_os_argv[0])(7) + 1;
因为此次运行时没有给命令行参数,所以 只有一个参数,也就是运行的程序名
接下来是:
for (i = 0; environ[i]; i++) {
if (ngx_os_argv_last == environ[i]) {
size = ngx_strlen(environ[i]) + 1;
ngx_os_argv_last = environ[i] + size;
ngx_cpystrn(p, (u_char *) environ[i], size);
environ[i] = (char *) p;
p += size;
}
}
现在 ngx_os_argv_last
等于环境变量的首地址
循环逻辑与上一个循环相同
ngx_os_argv_last
逐渐向后移
每次遍历还会将 环境变量依次迁移到新分配的内存
此次的运行情况:
i=0 ngx_os_argv_last(=0x7ffde3e967ae) == environ size(=20) = ngx_strlen(environ[0])(=19) + 1; ngx_os_argv_last(=0x7ffde3e967c2) = environ + size(=20); ngx_cpystrn(0x62a807451f20, 0x7ffde3e967ae, 20); environ = (char *) p(=0x62a807451f20); p(=0x62a807451f34) += size(=20);
i=1 ngx_os_argv_last(=0x7ffde3e967c2) == environ size(=18) = ngx_strlen(environ[1])(=17) + 1; ngx_os_argv_last(=0x7ffde3e967d4) = environ + size(=18); ngx_cpystrn(0x62a807451f34, 0x7ffde3e967c2, 18); environ = (char *) p(=0x62a807451f34); p(=0x62a807451f46) += size(=18);
i=2 ngx_os_argv_last(=0x7ffde3e967d4) == environ size(=23) = ngx_strlen(environ[2])(=22) + 1; ngx_os_argv_last(=0x7ffde3e967eb) = environ + size(=23); ngx_cpystrn(0x62a807451f46, 0x7ffde3e967d4, 23); environ = (char *) p(=0x62a807451f46); p(=0x62a807451f5d) += size(=23);
i=3 ngx_os_argv_last(=0x7ffde3e967eb) == environ size(=20) = ngx_strlen(environ[3])(=19) + 1; ngx_os_argv_last(=0x7ffde3e967ff) = environ + size(=20); ngx_cpystrn(0x62a807451f5d, 0x7ffde3e967eb, 20); environ = (char *) p(=0x62a807451f5d); p(=0x62a807451f71) += size(=20);
i=4 ngx_os_argv_last(=0x7ffde3e967ff) == environ size(=24) = ngx_strlen(environ[4])(=23) + 1; ngx_os_argv_last(=0x7ffde3e96817) = environ + size(=24); ngx_cpystrn(0x62a807451f71, 0x7ffde3e967ff, 24); environ = (char *) p(=0x62a807451f71); p(=0x62a807451f89) += size(=24);
i=5 ngx_os_argv_last(=0x7ffde3e96817) == environ size(=54) = ngx_strlen(environ[5])(=53) + 1; ngx_os_argv_last(=0x7ffde3e9684d) = environ + size(=54); ngx_cpystrn(0x62a807451f89, 0x7ffde3e96817, 54); environ = (char *) p(=0x62a807451f89); p(=0x62a807451fbf) += size(=54);
i=6 ngx_os_argv_last(=0x7ffde3e9684d) == environ size(=21) = ngx_strlen(environ[6])(=20) + 1; ngx_os_argv_last(=0x7ffde3e96862) = environ + size(=21); ngx_cpystrn(0x62a807451fbf, 0x7ffde3e9684d, 21); environ = (char *) p(=0x62a807451fbf); p(=0x62a807451fd4) += size(=21);
i=7 ngx_os_argv_last(=0x7ffde3e96862) == environ size(=17) = ngx_strlen(environ[7])(=16) + 1; ngx_os_argv_last(=0x7ffde3e96873) = environ + size(=17); ngx_cpystrn(0x62a807451fd4, 0x7ffde3e96862, 17); environ = (char *) p(=0x62a807451fd4); p(=0x62a807451fe5) += size(=17);
i=8 ngx_os_argv_last(=0x7ffde3e96873) == environ size(=1519) = ngx_strlen(environ[8])(=1518) + 1; ngx_os_argv_last(=0x7ffde3e96e62) = environ + size(=1519); ngx_cpystrn(0x62a807451fe5, 0x7ffde3e96873, 1519); environ = (char *) p(=0x62a807451fe5); p(=0x62a8074525d4) += size(=1519);
i=9 ngx_os_argv_last(=0x7ffde3e96e62) == environ size(=33) = ngx_strlen(environ[9])(=32) + 1; ngx_os_argv_last(=0x7ffde3e96e83) = environ + size(=33); ngx_cpystrn(0x62a8074525d4, 0x7ffde3e96e62, 33); environ = (char *) p(=0x62a8074525d4); p(=0x62a8074525f5) += size(=33);
i=10 ngx_os_argv_last(=0x7ffde3e96e83) == environ size(=20) = ngx_strlen(environ[10])(=19) + 1; ngx_os_argv_last(=0x7ffde3e96e97) = environ + size(=20); ngx_cpystrn(0x62a8074525f5, 0x7ffde3e96e83, 20); environ = (char *) p(=0x62a8074525f5); p(=0x62a807452609) += size(=20);
i=11 ngx_os_argv_last(=0x7ffde3e96e97) == environ size(=30) = ngx_strlen(environ[11])(=29) + 1; ngx_os_argv_last(=0x7ffde3e96eb5) = environ + size(=30); ngx_cpystrn(0x62a807452609, 0x7ffde3e96e97, 30); environ = (char *) p(=0x62a807452609); p(=0x62a807452627) += size(=30);
i=12 ngx_os_argv_last(=0x7ffde3e96eb5) == environ size(=11) = ngx_strlen(environ[12])(=10) + 1; ngx_os_argv_last(=0x7ffde3e96ec0) = environ + size(=11); ngx_cpystrn(0x62a807452627, 0x7ffde3e96eb5, 11); environ = (char *) p(=0x62a807452627); p(=0x62a807452632) += size(=11);
i=13 ngx_os_argv_last(=0x7ffde3e96ec0) == environ size(=25) = ngx_strlen(environ[13])(=24) + 1; ngx_os_argv_last(=0x7ffde3e96ed9) = environ + size(=25); ngx_cpystrn(0x62a807452632, 0x7ffde3e96ec0, 25); environ = (char *) p(=0x62a807452632); p(=0x62a80745264b) += size(=25);
i=14 ngx_os_argv_last(=0x7ffde3e96ed9) == environ size(=27) = ngx_strlen(environ[14])(=26) + 1; ngx_os_argv_last(=0x7ffde3e96ef4) = environ + size(=27); ngx_cpystrn(0x62a80745264b, 0x7ffde3e96ed9, 27); environ = (char *) p(=0x62a80745264b); p(=0x62a807452666) += size(=27);
i=15 ngx_os_argv_last(=0x7ffde3e96ef4) == environ size(=20) = ngx_strlen(environ[15])(=19) + 1; ngx_os_argv_last(=0x7ffde3e96f08) = environ + size(=20); ngx_cpystrn(0x62a807452666, 0x7ffde3e96ef4, 20); environ = (char *) p(=0x62a807452666); p(=0x62a80745267a) += size(=20);
i=16 ngx_os_argv_last(=0x7ffde3e96f08) == environ size(=76) = ngx_strlen(environ[16])(=75) + 1; ngx_os_argv_last(=0x7ffde3e96f54) = environ + size(=76); ngx_cpystrn(0x62a80745267a, 0x7ffde3e96f08, 76); environ = (char *) p(=0x62a80745267a); p(=0x62a8074526c6) += size(=76);
i=17 ngx_os_argv_last(=0x7ffde3e96f54) == environ size(=23) = ngx_strlen(environ[17])(=22) + 1; ngx_os_argv_last(=0x7ffde3e96f6b) = environ + size(=23); ngx_cpystrn(0x62a8074526c6, 0x7ffde3e96f54, 23); environ = (char *) p(=0x62a8074526c6); p(=0x62a8074526dd) += size(=23);
i=18 ngx_os_argv_last(=0x7ffde3e96f6b) == environ size(=20) = ngx_strlen(environ[18])(=19) + 1; ngx_os_argv_last(=0x7ffde3e96f7f) = environ + size(=20); ngx_cpystrn(0x62a8074526dd, 0x7ffde3e96f6b, 20); environ = (char *) p(=0x62a8074526dd); p(=0x62a8074526f1) += size(=20);
i=19 ngx_os_argv_last(=0x7ffde3e96f7f) == environ size(=13) = ngx_strlen(environ[19])(=12) + 1; ngx_os_argv_last(=0x7ffde3e96f8c) = environ + size(=13); ngx_cpystrn(0x62a8074526f1, 0x7ffde3e96f7f, 13); environ = (char *) p(=0x62a8074526f1); p(=0x62a8074526fe) += size(=13);
i=20 ngx_os_argv_last(=0x7ffde3e96f8c) == environ size(=10) = ngx_strlen(environ[20])(=9) + 1; ngx_os_argv_last(=0x7ffde3e96f96) = environ + size(=10); ngx_cpystrn(0x62a8074526fe, 0x7ffde3e96f8c, 10); environ = (char *) p(=0x62a8074526fe); p(=0x62a807452708) += size(=10);
i=21 ngx_os_argv_last(=0x7ffde3e96f96) == environ size(=11) = ngx_strlen(environ[21])(=10) + 1; ngx_os_argv_last(=0x7ffde3e96fa1) = environ + size(=11); ngx_cpystrn(0x62a807452708, 0x7ffde3e96f96, 11); environ = (char *) p(=0x62a807452708); p(=0x62a807452713) += size(=11);
i=22 ngx_os_argv_last(=0x7ffde3e96fa1) == environ size(=16) = ngx_strlen(environ[22])(=15) + 1; ngx_os_argv_last(=0x7ffde3e96fb1) = environ + size(=16); ngx_cpystrn(0x62a807452713, 0x7ffde3e96fa1, 16); environ = (char *) p(=0x62a807452713); p(=0x62a807452723) += size(=16);
i=23 ngx_os_argv_last(=0x7ffde3e96fb1) == environ size(=21) = ngx_strlen(environ[23])(=20) + 1; ngx_os_argv_last(=0x7ffde3e96fc6) = environ + size(=21); ngx_cpystrn(0x62a807452723, 0x7ffde3e96fb1, 21); environ = (char *) p(=0x62a807452723); p(=0x62a807452738) += size(=21);
i=24 ngx_os_argv_last(=0x7ffde3e96fc6) == environ size(=14) = ngx_strlen(environ[24])(=13) + 1; ngx_os_argv_last(=0x7ffde3e96fd4) = environ + size(=14); ngx_cpystrn(0x62a807452738, 0x7ffde3e96fc6, 14); environ = (char *) p(=0x62a807452738); p(=0x62a807452746) += size(=14);
i=25 ngx_os_argv_last(=0x7ffde3e96fd4) == environ size(=14) = ngx_strlen(environ[25])(=13) + 1; ngx_os_argv_last(=0x7ffde3e96fe2) = environ + size(=14); ngx_cpystrn(0x62a807452746, 0x7ffde3e96fd4, 14); environ = (char *) p(=0x62a807452746); p(=0x62a807452754) += size(=14);
i=26 ngx_os_argv_last(=0x7ffde3e96fe2) == environ size(=14) = ngx_strlen(environ[26])(=13) + 1; ngx_os_argv_last(=0x7ffde3e96ff0) = environ + size(=14); ngx_cpystrn(0x62a807452754, 0x7ffde3e96fe2, 14); environ = (char *) p(=0x62a807452754); p(=0x62a807452762) += size(=14);
接下来是:
ngx_os_argv_last--;
return NGX_OK;
ngx_os_argv_last 的值 -1, 指向原来存放环境变量的那片内存的最后一个字节
然后返回
回到 ngx_os_init
接下来是:
ngx_pagesize = getpagesize();
获取 当前系统一页的大小是多少字节
此次的情况
ngx_pagesize=4096
ngx_cacheline_size = NGX_CPU_CACHE_LINE;
存储 CPU 缓存行大小,默认值为 NGX_CPU_CACHE_LINE
目前的情况:
ngx_cacheline_size=64
for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ }
计算页面大小的对数( ngx_pagesize_shift
),即页面大小是 2 的多少次幂。
例如,4KB 的页面大小对应 ngx_pagesize_shift = 12
此次的情况:
ngx_pagesize_shift=12
if (ngx_ncpu == 0) {
ngx_ncpu = sysconf(_SC_NPROCESSORS_ONLN);
}
获取当前系统在线的 CPU 核心数
此次的情况是:
ngx_ncpu=2
if (ngx_ncpu < 1) {
ngx_ncpu = 1;
}
条件不成立,跳过这段代码
size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
if (size > 0) {
ngx_cacheline_size = size;
}
sysconf(_SC_LEVEL1_DCACHE_LINESIZE)
:获取一级缓存行大小
成功就更新 ngx_cacheline_size ,之前的值是默认值
此次的情况:
获取成功,但获得的值和默认值一样
ngx_cacheline_size=64
接下来是:
ngx_cpuinfo();
接下来是:
if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, errno,
"getrlimit(RLIMIT_NOFILE) failed");
return NGX_ERROR;
}
ngx_max_sockets = (ngx_int_t) rlmt.rlim_cur;
获取文件描述符数量的限制
此次的情况是:
ngx_max_sockets=1024
#if (NGX_HAVE_INHERITED_NONBLOCK || NGX_HAVE_ACCEPT4)
ngx_inherited_nonblocking = 1;
#else
ngx_inherited_nonblocking = 0;
#endif
ngx_inherited_nonblocking
:全局变量,指示当前环境是否支持继承非阻塞套接字
当前情况:
ngx_inherited_nonblocking=1
tp = ngx_timeofday();
srandom(((unsigned) ngx_pid << 16) ^ tp->sec ^ tp->msec);
return NGX_OK;
获取当前的时间缓存 用来 设置随机数种子
返回 NGX_OK
回到 main 函数中
接下来是:
if (ngx_crc32_table_init() != NGX_OK) {
return 1;
}
ngx_slab_sizes_init();
进入 ngx_slab_sizes_init
void
ngx_slab_sizes_init(void)
{
ngx_uint_t n;
ngx_slab_max_size = ngx_pagesize / 2;
ngx_slab_exact_size = ngx_pagesize / (8 * sizeof(uintptr_t));
for (n = ngx_slab_exact_size; n >>= 1; ngx_slab_exact_shift++) {
/* void */
}
}
此次的情况是:
ngx_slab_max_size=2048 ngx_slab_exact_size=64 ngx_slab_exact_shift=6
回到 main 函数中
接下来是:
if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
return 1;
}
进入 ngx_add_inherited_sockets
static ngx_int_t
ngx_add_inherited_sockets(ngx_cycle_t *cycle)
{
u_char *p, *v, *inherited;
ngx_int_t s;
ngx_listening_t *ls;
inherited = (u_char *) getenv(NGINX_VAR);
此次
inherited 是 null,没有需要继承的 套接字描述符
if (inherited == NULL) {
return NGX_OK;
}
返回 NGX_OK
回到 main 函数中
接下来是:
if (ngx_preinit_modules() != NGX_OK) {
return 1;
}
进入 ngx_preinit_modules
ngx_int_t
ngx_preinit_modules(void)
{
ngx_uint_t i;
for (i = 0; ngx_modules[i]; i++) {
ngx_modules[i]->index = i;
ngx_modules[i]->name = ngx_module_names[i];
}
ngx_modules_n = i;
ngx_max_module = ngx_modules_n + NGX_MAX_DYNAMIC_MODULES;
return NGX_OK;
}
进入循环,遍历 ngx_modules 数组
为每个模块的 index 和 name 字段赋值
此次的情况是:
ngx_modules[0]->index = 0 ngx_modules[0]->name = ngx_core_module ngx_modules[1]->index = 1 ngx_modules[1]->name = ngx_errlog_module ngx_modules[2]->index = 2 ngx_modules[2]->name = ngx_conf_module ngx_modules[3]->index = 3 ngx_modules[3]->name = ngx_openssl_module ngx_modules[4]->index = 4 ngx_modules[4]->name = ngx_regex_module ngx_modules[5]->index = 5 ngx_modules[5]->name = ngx_events_module ngx_modules[6]->index = 6 ngx_modules[6]->name = ngx_event_core_module ngx_modules[7]->index = 7 ngx_modules[7]->name = ngx_epoll_module ngx_modules[8]->index = 8 ngx_modules[8]->name = ngx_http_module ngx_modules[9]->index = 9 ngx_modules[9]->name = ngx_http_core_module ngx_modules[10]->index = 10 ngx_modules[10]->name = ngx_http_log_module ngx_modules[11]->index = 11 ngx_modules[11]->name = ngx_http_upstream_module ngx_modules[12]->index = 12 ngx_modules[12]->name = ngx_http_v2_module ngx_modules[13]->index = 13 ngx_modules[13]->name = ngx_http_static_module ngx_modules[14]->index = 14 ngx_modules[14]->name = ngx_http_gzip_static_module ngx_modules[15]->index = 15 ngx_modules[15]->name = ngx_http_autoindex_module ngx_modules[16]->index = 16 ngx_modules[16]->name = ngx_http_index_module ngx_modules[17]->index = 17 ngx_modules[17]->name = ngx_http_mirror_module ngx_modules[18]->index = 18 ngx_modules[18]->name = ngx_http_try_files_module ngx_modules[19]->index = 19 ngx_modules[19]->name = ngx_http_auth_basic_module ngx_modules[20]->index = 20 ngx_modules[20]->name = ngx_http_access_module ngx_modules[21]->index = 21 ngx_modules[21]->name = ngx_http_limit_conn_module ngx_modules[22]->index = 22 ngx_modules[22]->name = ngx_http_limit_req_module ngx_modules[23]->index = 23 ngx_modules[23]->name = ngx_http_geo_module ngx_modules[24]->index = 24 ngx_modules[24]->name = ngx_http_map_module ngx_modules[25]->index = 25 ngx_modules[25]->name = ngx_http_split_clients_module ngx_modules[26]->index = 26 ngx_modules[26]->name = ngx_http_referer_module ngx_modules[27]->index = 27 ngx_modules[27]->name = ngx_http_rewrite_module ngx_modules[28]->index = 28 ngx_modules[28]->name = ngx_http_ssl_module ngx_modules[29]->index = 29 ngx_modules[29]->name = ngx_http_proxy_module ngx_modules[30]->index = 30 ngx_modules[30]->name = ngx_http_fastcgi_module ngx_modules[31]->index = 31 ngx_modules[31]->name = ngx_http_uwsgi_module ngx_modules[32]->index = 32 ngx_modules[32]->name = ngx_http_scgi_module ngx_modules[33]->index = 33 ngx_modules[33]->name = ngx_http_grpc_module ngx_modules[34]->index = 34 ngx_modules[34]->name = ngx_http_memcached_module ngx_modules[35]->index = 35 ngx_modules[35]->name = ngx_http_empty_gif_module ngx_modules[36]->index = 36 ngx_modules[36]->name = ngx_http_browser_module ngx_modules[37]->index = 37 ngx_modules[37]->name = ngx_http_upstream_hash_module ngx_modules[38]->index = 38 ngx_modules[38]->name = ngx_http_upstream_ip_hash_module ngx_modules[39]->index = 39 ngx_modules[39]->name = ngx_http_upstream_least_conn_module ngx_modules[40]->index = 40 ngx_modules[40]->name = ngx_http_upstream_random_module ngx_modules[41]->index = 41 ngx_modules[41]->name = ngx_http_upstream_keepalive_module ngx_modules[42]->index = 42 ngx_modules[42]->name = ngx_http_upstream_zone_module ngx_modules[43]->index = 43 ngx_modules[43]->name = ngx_http_write_filter_module ngx_modules[44]->index = 44 ngx_modules[44]->name = ngx_http_header_filter_module ngx_modules[45]->index = 45 ngx_modules[45]->name = ngx_http_chunked_filter_module ngx_modules[46]->index = 46 ngx_modules[46]->name = ngx_http_v2_filter_module ngx_modules[47]->index = 47 ngx_modules[47]->name = ngx_http_range_header_filter_module ngx_modules[48]->index = 48 ngx_modules[48]->name = ngx_http_gzip_filter_module ngx_modules[49]->index = 49 ngx_modules[49]->name = ngx_http_postpone_filter_module ngx_modules[50]->index = 50 ngx_modules[50]->name = ngx_http_ssi_filter_module ngx_modules[51]->index = 51 ngx_modules[51]->name = ngx_http_charset_filter_module ngx_modules[52]->index = 52 ngx_modules[52]->name = ngx_http_userid_filter_module ngx_modules[53]->index = 53 ngx_modules[53]->name = ngx_http_headers_filter_module ngx_modules[54]->index = 54 ngx_modules[54]->name = ngx_http_copy_filter_module ngx_modules[55]->index = 55 ngx_modules[55]->name = ngx_http_range_body_filter_module ngx_modules[56]->index = 56 ngx_modules[56]->name = ngx_http_not_modified_filter_module ngx_modules[57]->index = 57 ngx_modules[57]->name = ngx_stream_module ngx_modules[58]->index = 58 ngx_modules[58]->name = ngx_stream_core_module ngx_modules[59]->index = 59 ngx_modules[59]->name = ngx_stream_log_module ngx_modules[60]->index = 60 ngx_modules[60]->name = ngx_stream_proxy_module ngx_modules[61]->index = 61 ngx_modules[61]->name = ngx_stream_upstream_module ngx_modules[62]->index = 62 ngx_modules[62]->name = ngx_stream_write_filter_module ngx_modules[63]->index = 63 ngx_modules[63]->name = ngx_stream_ssl_module ngx_modules[64]->index = 64 ngx_modules[64]->name = ngx_stream_limit_conn_module ngx_modules[65]->index = 65 ngx_modules[65]->name = ngx_stream_access_module ngx_modules[66]->index = 66 ngx_modules[66]->name = ngx_stream_geo_module ngx_modules[67]->index = 67 ngx_modules[67]->name = ngx_stream_map_module ngx_modules[68]->index = 68 ngx_modules[68]->name = ngx_stream_split_clients_module ngx_modules[69]->index = 69 ngx_modules[69]->name = ngx_stream_return_module ngx_modules[70]->index = 70 ngx_modules[70]->name = ngx_stream_set_module ngx_modules[71]->index = 71 ngx_modules[71]->name = ngx_stream_upstream_hash_module ngx_modules[72]->index = 72 ngx_modules[72]->name = ngx_stream_upstream_least_conn_module ngx_modules[73]->index = 73 ngx_modules[73]->name = ngx_stream_upstream_random_module ngx_modules[74]->index = 74 ngx_modules[74]->name = ngx_stream_upstream_zone_module
ngx_modules_n 静态模块的总数
ngx_max_module 表示Nginx支持的最大模块数量
NGX_MAX_DYNAMIC_MODULES 动态加载模块的最大数量
ngx_modules_n=75 ngx_max_module(=203) = ngx_modules_n(75) + NGX_MAX_DYNAMIC_MODULES(128)
回到 main 函数中
接下来是:
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;
}
调用 ngx_init_cycle
进入 ngx_init_cycle
ngx_cycle_t *
ngx_init_cycle(ngx_cycle_t *old_cycle)
{
void *rv;
char **senv;
ngx_uint_t i, n;
ngx_log_t *log;
ngx_time_t *tp;
ngx_conf_t conf;
ngx_pool_t *pool;
ngx_cycle_t *cycle, **old;
ngx_shm_zone_t *shm_zone, *oshm_zone;
ngx_list_part_t *part, *opart;
ngx_open_file_t *file;
ngx_listening_t *ls, *nls;
ngx_core_conf_t *ccf, *old_ccf;
ngx_core_module_t *module;
char hostname[NGX_MAXHOSTNAMELEN];
ngx_timezone_update();
/* force localtime update with a new timezone */
tp = ngx_timeofday();
tp->sec = 0;
ngx_time_update();
更新时间
log = old_cycle->log;
获取之前的 log 对象,暂时还是用它来记录 log
pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
if (pool == NULL) {
return NULL;
}
pool->log = log;
创建一个新的内存池,然后设置它使用的 log
此次的情况是:
pool = ngx_create_pool(16384, log) pool= 0x5f33e4db67b0 (地址)
接下来是:
cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));
if (cycle == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
此次的情况是:
cycle = ngx_pcalloc(pool, 648); cycle= 0x5c67408e7800
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;
}
给字段赋值
此次的情况是:
cycle->conf_prefix.len =28 cycle->conf_prefix.data=/home/wsd/桌面/nginx/conf/
cycle->prefix.len = old_cycle->prefix.len;
cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix);
if (cycle->prefix.data == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
此次的情况是:
cycle->prefix.len = 17) cycle->prefix.data= /usr/local/nginx/
cycle->error_log.len = old_cycle->error_log.len;
cycle->error_log.data = ngx_pnalloc(pool, old_cycle->error_log.len + 1);
if (cycle->error_log.data == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
ngx_cpystrn(cycle->error_log.data, old_cycle->error_log.data,
old_cycle->error_log.len + 1);
此次的情况是:
cycle->error_log.len=36
cycle->error_log.data=/home/wsd/桌面/nginx/LOG/error.log
cycle->conf_file.len = old_cycle->conf_file.len;
cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1);
if (cycle->conf_file.data == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data,
old_cycle->conf_file.len + 1);
此次的情况是:
cycle->conf_file.len=38 cycle->conf_file.data=/home/wsd/桌面/nginx/conf/nginx.conf
cycle->conf_param.len = old_cycle->conf_param.len;
cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param);
if (cycle->conf_param.data == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
此次的情况是:
cycle->conf_param.len=0 cycle->conf_param.data 是 null
运行时没有给命令行参数
n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10;
此次的情况是:
n = 0 ? 0 : 10; n=10
if (ngx_array_init(&cycle->paths, pool, n, sizeof(ngx_path_t *))
!= NGX_OK)
{
ngx_destroy_pool(pool);
return NULL;
}
ngx_memzero(cycle->paths.elts, n * sizeof(ngx_path_t *));
将 paths
数组的前 n
个元素清零
if (ngx_array_init(&cycle->config_dump, pool, 1, sizeof(ngx_conf_dump_t))
!= NGX_OK)
{
ngx_destroy_pool(pool);
return NULL;
}
初始化数组 config_dump
ngx_rbtree_init(&cycle->config_dump_rbtree, &cycle->config_dump_sentinel,
ngx_str_rbtree_insert_value);
if (old_cycle->open_files.part.nelts) {
n = old_cycle->open_files.part.nelts;
for (part = old_cycle->open_files.part.next; part; part = part->next) {
n += part->nelts;
}
} else {
n = 20;
}
此次运行的情况是:
old_cycle->open_files.part.nelts=0
所以进入 else n=20
if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))
!= NGX_OK)
{
ngx_destroy_pool(pool);
return NULL;
}
初始化新周期的 open_files
列表。
此次运行的情况是:
ngx_list_init(&cycle->open_files, pool, n =20 , sizeof(ngx_open_file_t) =40 )
if (old_cycle->shared_memory.part.nelts) {
n = old_cycle->shared_memory.part.nelts;
for (part = old_cycle->shared_memory.part.next; part; part = part->next)
{
n += part->nelts;
}
} else {
n = 1;
}
设置新周期的 shared_memory 的元素数量
此次运行的情况是:
old_cycle->shared_memory.part.nelts=0
所以 进入else n=1
if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t))
!= NGX_OK)
{
ngx_destroy_pool(pool);
return NULL;
}
初始化 shared_memory
此次运行的情况是:
ngx_list_init(&cycle->shared_memory, pool, n =1 , sizeof(ngx_shm_zone_t) =88 )
n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;
此次运行的情况是:
n( =10 ) = old_cycle->listening.nelts( =0 ) ? old_cycle->listening.nelts( =0 ) : 10
if (ngx_array_init(&cycle->listening, pool, n, sizeof(ngx_listening_t))
!= NGX_OK)
{
ngx_destroy_pool(pool);
return NULL;
}
初始化 cycle->listening
数组
此次运行的情况是:
ngx_array_init(&cycle->listening, pool, n( =10 ), sizeof(ngx_listening_t)( =296 ))
ngx_memzero(cycle->listening.elts, n * sizeof(ngx_listening_t));
将 cycle->listening
的
内存区域清 0
ngx_queue_init(&cycle->reusable_connections_queue);
cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
if (cycle->conf_ctx == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
从内存池 pool 中分配一个指针数组 conf_ctx ,每个元素对应一个模块的配置结构指针。
if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed");
ngx_destroy_pool(pool);
return NULL;
}
调用 gethostname()
系统调用获取本地主机名,存储到 hostname
缓冲区。
hostname[NGX_MAXHOSTNAMELEN - 1] = '\0';
cycle->hostname.len = ngx_strlen(hostname);
确保 hostname
以 \0
结尾
计算主机名的实际长度(不含终止符),存储到 cycle->hostname.len
cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len);
if (cycle->hostname.data == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
从内存池 pool
分配内存,存储主机名的副本
ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len);
将主机名转换为全小写,存储到 cycle->hostname.data
此次运行的情况是:
hostname=wsd-vm cycle->hostname.len=6 cycle->hostname.data = ngx_pnalloc(pool, 6) cycle->hostname.data=0x6165d5b590d0 地址 cycle->hostname.data = wsd-vm
if (ngx_cycle_modules(cycle) != NGX_OK) {
ngx_destroy_pool(pool);
return NULL;
}
调用 ngx_cycle_modules 初始化 cycle->modules 数组,该数组包含所有核心模块的指针
for (i = 0; cycle->modules[i]; i++) {
if (cycle->modules[i]->type != NGX_CORE_MODULE) {
continue;
}
遍历所有核心模块
module = cycle->modules[i]->ctx;
获取核心模块的配置
if (module->create_conf) {
rv = module->create_conf(cycle);
if (rv == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
cycle->conf_ctx[cycle->modules[i]->index] = rv;
}
}
调用模块的 create_conf 方法创建默认配置结构,并将其存储到 conf_ctx 数组的对应位置。
此次运行的情况是:
i=0 cycle->modules[0]->name = ngx_core_module cycle->modules[0]->type == NGX_CORE_MODULE module->create_conf = 0x5c9ee022c9b8 cycle->conf_ctx[0] = 0x5c9f13b4c738
i=1 cycle->modules[1]->name = ngx_errlog_module cycle->modules[1]->type == NGX_CORE_MODULE module->create_conf = (nil)
i=2 cycle->modules[2]->name = ngx_conf_module cycle->modules[2]->type != NGX_CORE_MODULE continue
i=3 cycle->modules[3]->name = ngx_openssl_module cycle->modules[3]->type == NGX_CORE_MODULE module->create_conf = 0x5c9ee02587ea cycle->conf_ctx[3] = 0x5c9f13b4c830
i=4 cycle->modules[4]->name = ngx_regex_module cycle->modules[4]->type == NGX_CORE_MODULE module->create_conf = 0x5c9ee0263174 cycle->conf_ctx[4] = 0x5c9f13b4c838
i=5 cycle->modules[5]->name = ngx_events_module cycle->modules[5]->type == NGX_CORE_MODULE module->create_conf = (nil)
i=6 cycle->modules[6]->name = ngx_event_core_module cycle->modules[6]->type != NGX_CORE_MODULE continue
i=7 cycle->modules[7]->name = ngx_epoll_module cycle->modules[7]->type != NGX_CORE_MODULE continue
i=8 cycle->modules[8]->name = ngx_http_module cycle->modules[8]->type == NGX_CORE_MODULE module->create_conf = (nil)
i=9 cycle->modules[9]->name = ngx_http_core_module cycle->modules[9]->type != NGX_CORE_MODULE continue
i=10 cycle->modules[10]->name = ngx_http_log_module cycle->modules[10]->type != NGX_CORE_MODULE continue
i=11 cycle->modules[11]->name = ngx_http_upstream_module cycle->modules[11]->type != NGX_CORE_MODULE continue
i=12 cycle->modules[12]->name = ngx_http_v2_module cycle->modules[12]->type != NGX_CORE_MODULE continue
i=13 cycle->modules[13]->name = ngx_http_static_module cycle->modules[13]->type != NGX_CORE_MODULE continue
i=14 cycle->modules[14]->name = ngx_http_gzip_static_module cycle->modules[14]->type != NGX_CORE_MODULE continue
i=15 cycle->modules[15]->name = ngx_http_autoindex_module cycle->modules[15]->type != NGX_CORE_MODULE continue
i=16 cycle->modules[16]->name = ngx_http_index_module cycle->modules[16]->type != NGX_CORE_MODULE continue
i=17 cycle->modules[17]->name = ngx_http_mirror_module cycle->modules[17]->type != NGX_CORE_MODULE continue
i=18 cycle->modules[18]->name = ngx_http_try_files_module cycle->modules[18]->type != NGX_CORE_MODULE continue
i=19 cycle->modules[19]->name = ngx_http_auth_basic_module cycle->modules[19]->type != NGX_CORE_MODULE continue
i=20 cycle->modules[20]->name = ngx_http_access_module cycle->modules[20]->type != NGX_CORE_MODULE continue
i=21 cycle->modules[21]->name = ngx_http_limit_conn_module cycle->modules[21]->type != NGX_CORE_MODULE continue
i=22 cycle->modules[22]->name = ngx_http_limit_req_module cycle->modules[22]->type != NGX_CORE_MODULE continue
i=23 cycle->modules[23]->name = ngx_http_geo_module cycle->modules[23]->type != NGX_CORE_MODULE continue
i=24 cycle->modules[24]->name = ngx_http_map_module cycle->modules[24]->type != NGX_CORE_MODULE continue
i=25 cycle->modules[25]->name = ngx_http_split_clients_module cycle->modules[25]->type != NGX_CORE_MODULE continue
i=26 cycle->modules[26]->name = ngx_http_referer_module cycle->modules[26]->type != NGX_CORE_MODULE continue
i=27 cycle->modules[27]->name = ngx_http_rewrite_module cycle->modules[27]->type != NGX_CORE_MODULE continue
i=28 cycle->modules[28]->name = ngx_http_ssl_module cycle->modules[28]->type != NGX_CORE_MODULE continue
i=29 cycle->modules[29]->name = ngx_http_proxy_module cycle->modules[29]->type != NGX_CORE_MODULE continue
i=30 cycle->modules[30]->name = ngx_http_fastcgi_module cycle->modules[30]->type != NGX_CORE_MODULE continue
i=31 cycle->modules[31]->name = ngx_http_uwsgi_module cycle->modules[31]->type != NGX_CORE_MODULE continue
i=32 cycle->modules[32]->name = ngx_http_scgi_module cycle->modules[32]->type != NGX_CORE_MODULE continue
i=33 cycle->modules[33]->name = ngx_http_grpc_module cycle->modules[33]->type != NGX_CORE_MODULE continue
i=34 cycle->modules[34]->name = ngx_http_memcached_module cycle->modules[34]->type != NGX_CORE_MODULE continue
i=35 cycle->modules[35]->name = ngx_http_empty_gif_module cycle->modules[35]->type != NGX_CORE_MODULE continue
i=36 cycle->modules[36]->name = ngx_http_browser_module cycle->modules[36]->type != NGX_CORE_MODULE continue
i=37 cycle->modules[37]->name = ngx_http_upstream_hash_module cycle->modules[37]->type != NGX_CORE_MODULE continue
i=38 cycle->modules[38]->name = ngx_http_upstream_ip_hash_module cycle->modules[38]->type != NGX_CORE_MODULE continue
i=39 cycle->modules[39]->name = ngx_http_upstream_least_conn_module cycle->modules[39]->type != NGX_CORE_MODULE continue
i=40 cycle->modules[40]->name = ngx_http_upstream_random_module cycle->modules[40]->type != NGX_CORE_MODULE continue
i=41 cycle->modules[41]->name = ngx_http_upstream_keepalive_module cycle->modules[41]->type != NGX_CORE_MODULE continue
i=42 cycle->modules[42]->name = ngx_http_upstream_zone_module cycle->modules[42]->type != NGX_CORE_MODULE continue
i=43 cycle->modules[43]->name = ngx_http_write_filter_module cycle->modules[43]->type != NGX_CORE_MODULE continue
i=44 cycle->modules[44]->name = ngx_http_header_filter_module cycle->modules[44]->type != NGX_CORE_MODULE continue
i=45 cycle->modules[45]->name = ngx_http_chunked_filter_module cycle->modules[45]->type != NGX_CORE_MODULE continue
i=46 cycle->modules[46]->name = ngx_http_v2_filter_module cycle->modules[46]->type != NGX_CORE_MODULE continue
i=47 cycle->modules[47]->name = ngx_http_range_header_filter_module cycle->modules[47]->type != NGX_CORE_MODULE continue
i=48 cycle->modules[48]->name = ngx_http_gzip_filter_module cycle->modules[48]->type != NGX_CORE_MODULE continue
i=49 cycle->modules[49]->name = ngx_http_postpone_filter_module cycle->modules[49]->type != NGX_CORE_MODULE continue
i=50 cycle->modules[50]->name = ngx_http_ssi_filter_module cycle->modules[50]->type != NGX_CORE_MODULE continue
i=51 cycle->modules[51]->name = ngx_http_charset_filter_module cycle->modules[51]->type != NGX_CORE_MODULE continue
i=52 cycle->modules[52]->name = ngx_http_userid_filter_module cycle->modules[52]->type != NGX_CORE_MODULE continue
i=53 cycle->modules[53]->name = ngx_http_headers_filter_module cycle->modules[53]->type != NGX_CORE_MODULE continue
i=54 cycle->modules[54]->name = ngx_http_copy_filter_module cycle->modules[54]->type != NGX_CORE_MODULE continue
i=55 cycle->modules[55]->name = ngx_http_range_body_filter_module cycle->modules[55]->type != NGX_CORE_MODULE continue
i=56 cycle->modules[56]->name = ngx_http_not_modified_filter_module cycle->modules[56]->type != NGX_CORE_MODULE continue
i=57 cycle->modules[57]->name = ngx_stream_module cycle->modules[57]->type == NGX_CORE_MODULE module->create_conf = (nil)
i=58 cycle->modules[58]->name = ngx_stream_core_module cycle->modules[58]->type != NGX_CORE_MODULE continue
i=59 cycle->modules[59]->name = ngx_stream_log_module cycle->modules[59]->type != NGX_CORE_MODULE continue
i=60 cycle->modules[60]->name = ngx_stream_proxy_module cycle->modules[60]->type != NGX_CORE_MODULE continue
i=61 cycle->modules[61]->name = ngx_stream_upstream_module cycle->modules[61]->type != NGX_CORE_MODULE continue
i=62 cycle->modules[62]->name = ngx_stream_write_filter_module cycle->modules[62]->type != NGX_CORE_MODULE continue
i=63 cycle->modules[63]->name = ngx_stream_ssl_module cycle->modules[63]->type != NGX_CORE_MODULE continue
i=64 cycle->modules[64]->name = ngx_stream_limit_conn_module cycle->modules[64]->type != NGX_CORE_MODULE continue
i=65 cycle->modules[65]->name = ngx_stream_access_module cycle->modules[65]->type != NGX_CORE_MODULE continue
i=66 cycle->modules[66]->name = ngx_stream_geo_module cycle->modules[66]->type != NGX_CORE_MODULE continue
i=67 cycle->modules[67]->name = ngx_stream_map_module cycle->modules[67]->type != NGX_CORE_MODULE continue
i=68 cycle->modules[68]->name = ngx_stream_split_clients_module cycle->modules[68]->type != NGX_CORE_MODULE continue
i=69 cycle->modules[69]->name = ngx_stream_return_module cycle->modules[69]->type != NGX_CORE_MODULE continue
i=70 cycle->modules[70]->name = ngx_stream_set_module cycle->modules[70]->type != NGX_CORE_MODULE continue
i=71 cycle->modules[71]->name = ngx_stream_upstream_hash_module cycle->modules[71]->type != NGX_CORE_MODULE continue
i=72 cycle->modules[72]->name = ngx_stream_upstream_least_conn_module cycle->modules[72]->type != NGX_CORE_MODULE continue
i=73 cycle->modules[73]->name = ngx_stream_upstream_random_module cycle->modules[73]->type != NGX_CORE_MODULE continue
i=74 cycle->modules[74]->name = ngx_stream_upstream_zone_module cycle->modules[74]->type != NGX_CORE_MODULE continue
第一个模块是 ngx_core_module
它的 create_conf 存在
进入 它的 create_conf
第二个 NGX_CORE_MODULE 模块是 ngx_errlog_module
它的 create_conf 是NULL
下一个有 create_conf 的 NGX_CORE_MODULE 模块 是
ngx_openssl_module
下一个有 create_conf 的 NGX_CORE_MODULE 模块 是
ngx_regex_module
接下来是:
senv = environ;
ngx_memzero(&conf, sizeof(ngx_conf_t));
conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t));
if (conf.args == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
if (conf.temp_pool == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
conf.ctx = cycle->conf_ctx;
conf.cycle = cycle;
conf.pool = pool;
conf.log = log;
conf.module_type = NGX_CORE_MODULE;
conf.cmd_type = NGX_MAIN_CONF;
if (ngx_conf_param(&conf) != NGX_CONF_OK) {
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}