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_atoi
Ubuntu 下 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_push
Ubuntu 下 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_sockets
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_set_inherited_sockets-CSDN博客