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); if (inherited == NULL) { return NGX_OK; } printf("inherited: %s\n", inherited); ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "using inherited sockets from \"%s\"", inherited); if (ngx_array_init(&cycle->listening, cycle->pool, 10, sizeof(ngx_listening_t)) != NGX_OK) { return NGX_ERROR; } for (p = inherited, v = p; *p; p++) { if (*p == ':' || *p == ';') { s = ngx_atoi(v, p - v); if (s == NGX_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "invalid socket number \"%s\" in " NGINX_VAR " environment variable, ignoring the rest" " of the variable", v); break; } v = p + 1; ls = ngx_array_push(&cycle->listening); if (ls == NULL) { return NGX_ERROR; } ngx_memzero(ls, sizeof(ngx_listening_t)); ls->fd = (ngx_socket_t) s; } } if (v != p) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "invalid socket number \"%s\" in " NGINX_VAR " environment variable, ignoring", v); } ngx_inherited = 1; return ngx_set_inherited_sockets(cycle); }
// 参考:http://blog.csdn.net/livelylittlefish/article/details/7277607 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); // 从environ 中查看是否设置了NGINX_VAR这个环境变量。若设置了,则要SOCKET继承 if (inherited == NULL) { return NGX_OK; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "using inherited sockets from \"%s\"", inherited); if (ngx_array_init(&cycle->listening, cycle->pool, 10, sizeof(ngx_listening_t)) != NGX_OK) { return NGX_ERROR; } // 为了便于调试,设置 export NGINX="16000:16500:16600;" for (p = inherited, v = p; *p; p++) { if (*p == ':' || *p == ';') { s = ngx_atoi(v, p - v); if (s == NGX_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "invalid socket number \"%s\" in " NGINX_VAR " environment variable, ignoring the rest" " of the variable", v); break; } v = p + 1; ls = ngx_array_push(&cycle->listening); if (ls == NULL) { return NGX_ERROR; } ngx_memzero(ls, sizeof(ngx_listening_t)); ls->fd = (ngx_socket_t) s; } } // 全局变量,定义于/os/unix/ngx_process_cycle.c 文件中 ngx_inherited = 1; // 定义于./core/ngx_connection.c 文件中 return ngx_set_inherited_sockets(cycle); }
/*继承socket*/ 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; //#define NGINX_VAR "NGINX" inherited = (u_char *) getenv(NGINX_VAR); // 查看是否有设置NGINX这个环境变量 if (inherited == NULL) {//直接返回 return NGX_OK; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "using inherited sockets from \"%s\"", inherited); if (ngx_array_init(&cycle->listening, cycle->pool, 10, sizeof(ngx_listening_t)) != NGX_OK) { return NGX_ERROR; } for (p = inherited, v = p; *p; p++) { if (*p == ':' || *p == ';') { //通过冒号或分号去除列表中的socket s = ngx_atoi(v, p - v); if (s == NGX_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "invalid socket number \"%s\" in " NGINX_VAR " environment variable, ignoring the rest" " of the variable", v); break; } v = p + 1; ls = ngx_array_push(&cycle->listening); //保存取出来的socket if (ls == NULL) { return NGX_ERROR; } ngx_memzero(ls, sizeof(ngx_listening_t)); ls->fd = (ngx_socket_t) s; } } ngx_inherited = 1; //标记继承工作的结束 return ngx_set_inherited_sockets(cycle); }
/* 图8-6中的第2步实际上就是在调用表812中的ngx_add_inherited_ sockets方法。Nginx在不重启服务升级时,也就是我们说过的平滑升级(参见1.9节)时, 它会不重启master进程而启动新版本的Nginx程序。这样,旧版本的master进程会通过execve系统调用来启动新版本的master进程(先fork出子进程再 调用exec来运行新程序),这时旧版本的master进程必须要通过一种方式告诉新版本的master进程这是在平滑升级,并且传递一些必要的信息。Nginx是通过环 境变量来传递这些信息的,新版本的master进程通过ngx_add_inherited_sockets方法由环境变量里读取平滑升级信息,并对旧版本Nginx服务监听的句柄做继承处理。 */ 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; //getenv()用来取得参数envvar环境变量的内容。参数envvar为环境变量的名称,如果该变量存在则会返回指向该内容的指针 inherited = (u_char *) getenv(NGINX_VAR); //获取环境变量 这里的"NGINX_VAR"是宏定义,值为"NGINX" if (inherited == NULL) { return NGX_OK; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "using inherited sockets from \"%s\"", inherited); //初始化ngx_cycle.listening数组,并且数组中包含10个元素 if (ngx_array_init(&cycle->listening, cycle->pool, 10, sizeof(ngx_listening_t)) != NGX_OK) { return NGX_ERROR; } for (p = inherited, v = p; *p; p++) { //遍历环境变量 if (*p == ':' || *p == ';') {//环境变量的值以':'or';'分开 s = ngx_atoi(v, p - v); //转换十进制sockets if (s == NGX_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "invalid socket number \"%s\" in " NGINX_VAR " environment variable, ignoring the rest" " of the variable", v); break; } v = p + 1; ls = ngx_array_push(&cycle->listening); //返回新分配的数组指针地址(在参考的blog里面这里解释可能有点错误) if (ls == NULL) { return NGX_ERROR; } ngx_memzero(ls, sizeof(ngx_listening_t)); ls->fd = (ngx_socket_t) s;//保存socket文件描述符到数组中 } } ngx_inherited = 1; //表示已经的得到要继承的socket return ngx_set_inherited_sockets(cycle); }
/* * Nginx在不重启服务升级时,即平滑升级的时候,它会不重启master进程而启动新版本的nginx程序。 * 这样旧版本的master进程会通过execve系统调用来启动新版本的master进程。这是旧版本的master * 进程必须通过一种方式告诉新版本的master进程这是在平滑升级,并且传递一些必要的信息。Nginx * 是通过环境变量(NGINX)来传递这些信息的。新版本的master进程通过ngx_add_inherited_sockets() * 方法由环境变量里读取平滑升级信息,并对旧版本Nginx服务监听的句柄做继承处理。 */ 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; /*获取环境变量,NGINX*/ inherited = (u_char *) getenv(NGINX_VAR); /*如果inherited为NULL,表明不是平滑升级,及环境变量NGINX是空的*/ if (inherited == NULL) { return NGX_OK; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "using inherited sockets from \"%s\"", inherited); /*初始化cycle->listening动态数组,初始情况下为十个ngx_listening_t元素*/ if (ngx_array_init(&cycle->listening, cycle->pool, 10, sizeof(ngx_listening_t)) != NGX_OK) { return NGX_ERROR; } /*遍历环境变量,获取旧版本Nginx服务所监听的socket句柄,做继承处理*/ for (p = inherited, v = p; *p; p++) { if (*p == ':' || *p == ';') { s = ngx_atoi(v, p - v); //字符串转整数 if (s == NGX_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "invalid socket number \"%s\" in " NGINX_VAR " environment variable, ignoring the rest" " of the variable", v); break; } /*在这个循环遍历处理过程中,v始终都指向下一个待转换的字符串形式的socket句柄的开始处*/ /*这种处理方法值得学习*/ v = p + 1; /*将解析得到的socket句柄存放在动态数组cycle->listening中*/ ls = ngx_array_push(&cycle->listening); if (ls == NULL) { return NGX_ERROR; } ngx_memzero(ls, sizeof(ngx_listening_t)); ls->fd = (ngx_socket_t) s; } } if (v != p) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "invalid socket number \"%s\" in " NGINX_VAR " environment variable, ignoring", v); } ngx_inherited = 1; //对旧版本nginx服务监听的socket句柄进行了继承标志位。 /*根据从旧版本Nginx中继承来的socket句柄,初始化socket对应的ngx_listening_t结构体的成员*/ return ngx_set_inherited_sockets(cycle); }
// 检查NGINX环境变量,获取之前监听的socket 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; // 获取环境变量,NGINX_VAR定义在nginx.h,值是"NGINX" inherited = (u_char *) getenv(NGINX_VAR); // 无变量则直接 if (inherited == NULL) { return NGX_OK; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "using inherited sockets from \"%s\"", inherited); // 清空cycle的监听端口数组 if (ngx_array_init(&cycle->listening, cycle->pool, 10, sizeof(ngx_listening_t)) != NGX_OK) { return NGX_ERROR; } // 从环境变量字符串里切分出socket for (p = inherited, v = p; *p; p++) { // 分隔符是:/; if (*p == ':' || *p == ';') { s = ngx_atoi(v, p - v); if (s == NGX_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "invalid socket number \"%s\" in " NGINX_VAR " environment variable, ignoring the rest" " of the variable", v); break; } v = p + 1; ls = ngx_array_push(&cycle->listening); if (ls == NULL) { return NGX_ERROR; } ngx_memzero(ls, sizeof(ngx_listening_t)); ls->fd = (ngx_socket_t) s; } } if (v != p) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "invalid socket number \"%s\" in " NGINX_VAR " environment variable, ignoring", v); } ngx_inherited = 1; // in ngx_connection.c return ngx_set_inherited_sockets(cycle); }