我们在通过ps -ef | grep nginx 查看Nginx的进程时,会发现显示的名称有些与众不同,如下所示
root@test:/home/test# ps -ef | grep nginx
root 2047 1 0 01:58 ? 00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
www-data 2048 2047 0 01:58 ? 00:00:00 nginx: worker process
www-data 2049 2047 0 01:58 ? 00:00:00 nginx: worker process
root 2230 2073 0 02:20 pts/3 00:00:00 grep --color=auto nginx
master进程名称与我们熟知的"可执行程序+参数列表"格式有些不同,为什么会这样呢?原因可以从Nginx的源码中找出。
答案在os/unix/ngx_setproctitle.c这个源代码中,ngx_setproctitle方法可以将Nginx进程名称修改为任意的字符串,不过在执行这个操作之前我们需要使用ngx_init_setproctitle来进行一些的准备工作。
其实原理很简单,程序入口函数main可以带2个参数,int argc和char *argv[],argc就是程序执行时的参数个数,argv的每个元素都指向对应索引的参数,其中argv[0]就存放着进程名称,我们只需要替换掉这个地址的内容就可以实现修改进程名称的目的。
当然,实际工作不会这么简单,因为当程序运行时指定参数时,这些参数包括argv[0]会存放在一个连续的内存空间中,并且会紧邻,举栗子,当我们运行“nginx -c /etc/nginx/nginc.conf”时,argc为3,这3个参数在内存中的存放形式为nginx\0-c\0/etc/nginx/nginx.conf\0。这意味着如果我们替换的进程名称过长时,会覆盖掉其他参数的内容。
另外,进程的环境变量的存放地址也是紧邻参数列表之后,也可能会被覆盖。因此ngx_init_setproctitle需要做一些准备工作将这些环境变量拷贝到另一块内存空间。
当我们想要替换的进程名称比原来的进程名称所占内存要少时,其实我们只需要memcpy(argv[0], <新进程名称>, strlen(<新进程名称>) + 1)即可