ngx_init_setproctitle
声明在 src/os/unix/ngx_setproctitle.h
ngx_int_t ngx_init_setproctitle(ngx_log_t *log);
定义在 src/os/unix/ngx_setproctitle.c
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; } p = ngx_alloc(size, log); if (p == NULL) { return NGX_ERROR; } 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; } } 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--; return NGX_OK; }
ngx_init_setproctitle是一个用于初始化进程标题(process title)修改功能的函数。它的主要目的是通过重新分配和整理环境变量的存储空间,为后续修改进程标题腾出连续的内存区域
在类 Unix 系统中,每个进程都有一个标题(process title),通常显示在ps或top命令中动态修改进程标题,以便更好地描述进程的状态
例如,主进程可能会显示为
master process,而工作进程可能会显示为worker process。当一个进程启动时,操作系统会为该进程分配一块连续的内存区域,用于存储以下内容
命令行参数 环境变量
这些数据通常存储在进程地址空间的高地址区域(靠近栈的底部),并且是连续的
操作系统会将进程标题初始化为命令行参数的内容(即
argv[0]及其后续参数)例如,假设启动了一个进程:
$ ./my_program arg1 arg2那么,操作系统的内存布局可能如下:
+-------------------+-------------------+-------------------+ | argv[0] | argv[1] | environ | +-------------------+-------------------+-------------------+ ^ ^ ^ | | | argv[0] argv[1] environ[0]进程标题就是
argv[0]的内容(即"./my_program")现在需要修改
argv[0] 的内容,修改后的内容如果比原来的内容需要的内存空间更多的话就会覆盖掉后面的内容,导致数据丢失,所以需要重新分配存储空间主要逻辑
原始内存布局: +----------------+----------------+----------------+----------------+ | argv[0] | argv[1] | ... (argv) | environ[0] | environ[1] ... +----------------+----------------+----------------+----------------+ ↑ ↑ ↑ ↑ ngx_os_argv[0] ngx_os_argv[1] ... environ[0] 迁移后布局: +----------------+----------------+----------------+----------------+ | argv[0] | argv[1] | ... (argv) | [空闲区域] | +----------------+----------------+----------------+----------------+ ↑ ngx_os_argv_last(可用的最后一个字节的位置) [空闲区域]原environ区域(现可安全覆盖) 新分配的内存块p: +----------------+----------------+----------------+ | environ[0] | environ[1] | ... (environ) | +----------------+----------------+----------------+ ↑ ↑ environ[0]新指向 environ[1]新指向 ngx_int_t ngx_init_setproctitle(ngx_log_t *log) { u_char *p; size_t size; ngx_uint_t i; size = 0;
作用 :定义变量并初始化。
p:指向新分配的内存区域,用于存储环境变量。
size:用于计算环境变量的总大小。
i:循环计数器。初始化
size为 0,表示尚未计算任何环境变量的大小。
for (i = 0; environ[i]; i++) { size += ngx_strlen(environ[i]) + 1; }作用 :遍历全局变量
environ(存储环境变量的数组),计算所有环境变量字符串的总长度。
environ[i]:当前环境变量字符串。
ngx_strlen(environ[i]) + 1:计算当前环境变量的长度,并加上终止符\0的长度。最终得到的
size是所有环境变量占用的总字节数。
p = ngx_alloc(size, log); if (p == NULL) { return NGX_ERROR; }作用 :分配一块连续的内存空间,大小为
size
如果分配失败,返回错误码
NGX_ERROR,表示初始化失败。
ngx_os_argv_last = ngx_os_argv[0];作用 :初始化
ngx_os_argv_last,指向命令行参数的第一个元素。
ngx_os_argv是存储命令行参数的数组。
ngx_os_argv_last将用于标记命令行参数和环境变量的末尾地址
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; } }作用 :找到命令行参数的末尾地址
遍历
ngx_os_argv数组,逐个检查每个命令行参数每次更新
ngx_os_argv_last为当前参数的末尾地址(包括终止符\0)这一步确保
ngx_os_argv_last指向命令行参数的最后一个有效字符之后的位置
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; } }作用 :将环境变量复制到新分配的内存区域。
遍历
environ数组,逐个处理每个环境变量。如果当前环境变量的地址等于
ngx_os_argv_last,说明它位于命令行参数的末尾。计算当前环境变量的长度(包括终止符
\0)。使用
ngx_cpystrn将环境变量复制到新内存区域。更新
environ[i]指向新内存中的位置。移动指针
p到下一个可用位置。
ngx_os_argv_last--;作用 :调整
ngx_os_argv_last的位置。
将
ngx_os_argv_last回退一个字节,使其指向最后一个有效字符的位置。这是为了确保后续修改进程标题时,不会覆盖无效的内存区域。
return NGX_OK;}
作用:返回成功状态。
- 如果所有操作成功完成,返回
NGX_OK,表示初始化成功
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_init_setproctitle函数
若云止水2025-02-21 11:22
相关推荐
zhuyasen1 小时前
Go Web 开发利器:如何让你的 Gin 服务拥有 Nginx 般的静态文件处理能力?achi0101 小时前
Ubuntu 24.04 LTS 下 Vue 3 开发环境搭建与生产部署完整指南数据库学啊1 小时前
团队小希望运维简单,时序数据库选型有什么推荐?霍格沃兹软件测试开发2 小时前
Playwright MCP浏览器自动化指南:让AI精准理解你的命令郝学胜-神的一滴3 小时前
Linux命名管道:创建与原理详解wanhengidc3 小时前
云手机性能如何?wan_da_ren3 小时前
Docker安装Elasticsearch9.2.1与Kibana9.2.1 保姆教程(带验证版)Eric.Lee20215 小时前
ubuntu 安装 Miniconda杭州泽沃电子科技有限公司5 小时前
在线监测:为医药精细化工奠定安全、合规与质量基石行初心5 小时前
uos基础 cupsd.conf 查看打印服务的配置文件