Ubuntu 下 nginx-1.24.0 源码分析 - ngx_add_inherited_sockets函数
ngx_add_inherited_sockets
声明在 src\core\nginx.c
static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle);
实现在 src\core\nginx.c
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; } 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; ls->inherited = 1; } } 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); }
static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle)
- 返回值 :
ngx_int_t类型,表示操作结果。成功返回NGX_OK,失败返回NGX_ERROR。- 参数 :
cycle:指向当前 Nginx 运行周期的结构体指针,包含运行时的所有核心配置和状态信息。
inherited = (u_char *) getenv(NGINX_VAR); if (inherited == NULL) { return NGX_OK; }
- 作用 :尝试从环境变量
NGINX_VAR中获取父进程遗留的监听套接字描述符。- 逻辑 :
- 如果环境变量不存在(即没有继承的套接字),函数直接返回
NGX_OK,表示无需进一步处理。- 环境变量的内容格式通常是
"fd1:fd2:fd3;",其中每个fd是一个整数,表示文件描述符。
NGINX_VAR
声明在 src/core/nginx.h
#define NGINX_VAR "NGINX"
getenv是 C 语言中的一个标准库函数,用于获取环境变量的值其声明在
<stdlib.h>头文件中,原型为
char *getenv(const char *name)通过传入环境变量名作为参数,
getenv返回该变量对应的值。如果变量不存在,则返回NULL返回类型:返回一个指向以 null 结尾的字符串的指针,该字符串即为环境变量的值
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; }
- 作用 :
- 打印日志,通知用户正在使用继承的套接字。
- 初始化
cycle->listening数组,用于存储监听套接字的相关信息。- 逻辑 :
ngx_array_init函数初始化一个动态数组,初始容量为 10,每个元素大小为sizeof(ngx_listening_t)。- 如果初始化失败(例如内存不足),函数返回
NGX_ERROR。
ngx_array_init
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_array_init 函数-CSDN博客
解析环境变量并提取文件描述符
for (p = inherited, v = p; *p; p++) {作用 :遍历环境变量字符串
inherited,逐个字符检查分隔符。
p是当前遍历的指针,v记录当前子字符串的起始位置。循环条件
*p表示只要字符串未结束就继续遍历。
if (*p == ':' || *p == ';') {作用 :检测当前字符是否为分隔符(
:或;)。分隔符用于区分不同的文件描述符。
s = ngx_atoi(v, p - v);作用 :将子字符串
v到p转换为整数(文件描述符)
ngx_atoi是 Nginx 提供的工具函数,用于将字符串转换为整数。
p - v表示子字符串的长度。
ngx_atoiUbuntu 下 nginx-1.24.0 源码分析 - ngx_atoi 函数-CSDN博客
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;作用 :更新子字符串的起始位置。
逻辑 :
将
v移动到当前分隔符的下一个字符,准备解析下一个文件描述符。
ls = ngx_array_push(&cycle->listening);作用 :在
cycle->listening数组中分配一个新的ngx_listening_t元素。逻辑 :
ngx_array_push动态扩展数组,并返回指向新元素的指针。
ngx_array_pushUbuntu 下 nginx-1.24.0 源码分析 - ngx_array_push-CSDN博客
if (ls == NULL) { return NGX_ERROR; }作用 :检查内存分配是否成功。
如果分配失败,函数返回
NGX_ERROR。
ngx_memzero(ls, sizeof(ngx_listening_t));
作用 :清零新分配的
ngx_listening_t结构体确保结构体所有字段初始值为 0
ls->fd = (ngx_socket_t) s; ls->inherited = 1;作用 :设置监听套接字的文件描述符和继承标志位。
ls->fd存储文件描述符。
ls->inherited标记该套接字是从父进程继承的。
处理未完成的解析
if (v != p) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "invalid socket number \"%s\" in " NGINX_VAR " environment variable, ignoring", v); }
作用 :检查是否还有未解析的部分(如缺少分隔符的情况)。
如果
v != p,说明最后一段数据未被正确解析,记录错误日志。
设置全局标志位
ngx_inherited = 1;
作用 :设置全局变量
ngx_inherited,标记当前进程已经继承了监听套接字。
调用辅助函数设置套接字属性
return ngx_set_inherited_sockets(cycle);
作用 :调用
ngx_set_inherited_sockets函数,进一步设置继承的套接字属性如果设置失败,函数返回
NGX_ERROR。
ngx_set_inherited_socketsUbuntu 下 nginx-1.24.0 源码分析 - ngx_set_inherited_sockets-CSDN博客
