Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1504021
  • 博文数量: 228
  • 博客积分: 1698
  • 博客等级: 上尉
  • 技术积分: 3241
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-24 21:49
个人简介

Linux

文章分类

全部博文(228)

文章存档

2017年(1)

2016年(43)

2015年(102)

2014年(44)

2013年(5)

2012年(30)

2011年(3)

分类: LINUX

2015-09-23 22:01:40

写在前面:代码比较简单,实际上修改的进程名字也是有限制,可以看到ngx_setproctitle中拷贝时有长度限制,超过原始内存长度时会被截断。。。
=========================================================================
转自: />
Linux下用ps命令可以看到显示的进程名字。这个进程的名字会体现在它的main()函数的入参中。main函数的原型:

点击(此处)折叠或打开

  1. int main(int argc, char *const *argv)

argc是表示命令行参数的个数;argv[]则用于以字符串形式存储所有的命令行参数内容,Linux中进程的名称就存储在argv[0]中。Linux还有个环境变量参数信息,表示进程执行需要的所有环境变量信息,通过一个全局变量Char **environ;来访问环境变量。

argv[]与environ两个变量所占的内存是连续的,并且是environ紧跟在argv[]后面。测试如下:

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <string.h>
  3.   
  4. extern char **environ;
  5.   
  6. int main(int argc , char *argv[])
  7. {
  8.     int i;
  9.   
  10.     printf("argc:%d\n" , argc);
  11.   
  12.     for (i = 0; i < argc; i++)
  13.     {
  14.         printf("argv[%d]:%s\t0x%x\n" , i , argv[i], argv[i]);
  15.     }
  16.   
  17.     for (i = 0; i < argc && environ[i]; i++)
  18.     {
  19.         printf("evriron[%d]:%s\t0x%x\n" , i , evriron[i], evriron[i]);
  20.     }
  21.   
  22.     return 0;
  23. }
测试结果如下:


修改进程名称
修改进程名称,正常只需要修改argv[0]指向的内存的值为所需要的值即可。但当要修改的值超过argv[0]所指向的内存空间大小时,直接修改可能覆盖掉后面的内容

此时必须重新分配一块连续的内存空间,把arg和environ的参数复制到新的空间,然后修改argv[0]


看一下Nginx是怎么做的

点击(此处)折叠或打开

  1. extern char **environ; // 全局变量,看完上面,你懂得
  2.   
  3. static char *ngx_os_argv_last; // 指向argv[]最后一个变量
  4.   
  5. /先做初始化,完成environ的内容拷贝到新的内存空间 */
  6. ngx_int_t  ngx_init_setproctitle(ngx_log_t *log)
  7. {
  8.     u_char *p;
  9.     size_t size;
  10.     ngx_uint_t i;
  11.   
  12.     size = 0;
  13.   
  14.     /* 计算environ[]的总大小 */
  15.     for (i = 0; environ[i]; i++) {
  16.         size += ngx_strlen(environ[i]) + 1;
  17.     }
  18.   
  19.     /* 申请同environ大小的内存空间 */
  20.     p = ngx_alloc(size, log);
  21.     if (p == NULL) {
  22.         return NGX_ERROR;
  23.     }
  24.   
  25.     /* 初始化argv[]首尾指针 */
  26.     ngx_os_argv_last = ngx_os_argv[0];
  27.   
  28.     /* 移动argv_last指针到argv[]尾部 */
  29.     for (i = 0; ngx_os_argv[i]; i++) {
  30.         if (ngx_os_argv_last == ngx_os_argv[i]) {
  31.             ngx_os_argv_last = ngx_os_argv[i] + ngx_strlen(ngx_os_argv[i]) + 1;
  32.         }
  33.     }
  34.   
  35.     /* 将environ的内容拷贝到刚申请的内存中去 */
  36.     for (i = 0; environ[i]; i++) {
  37.         if (ngx_os_argv_last == environ[i]) {
  38.   
  39.             size = ngx_strlen(environ[i]) + 1;
  40.             ngx_os_argv_last = environ[i] + size;
  41.   
  42.             ngx_cpystrn(p, (u_char *) environ[i], size);
  43.             environ[i] = (char *) p; // 这一步就是将environ中的变量重新指向刚分配的内存
  44.             p += size;
  45.         }
  46.     }
  47.   
  48.     ngx_os_argv_last--;
  49.   
  50.     return NGX_OK;
  51. }
完成上面的初始化后,就可以放心修改argv[0]的内容,然后看下具体的ngx_setproctitle()函数

点击(此处)折叠或打开

  1. void ngx_setproctitle(char *title)
  2. {
  3.     u_char *p;
  4.   
  5. /* 针对Solaris系统 */
  6. #if (NGX_SOLARIS)
  7.   
  8.     ngx_int_t i;
  9.     size_t size;
  10.   
  11. #endif
  12.   
  13.     ngx_os_argv[1] = NULL;
  14.   
  15.     /* 注意ngx_os_argv_last目前指向原始environ内存的最后一个参数,此时ngx_os_argv_last - ngx_os_argv[0]是原始argv和environ的总体大小 */
  16.     p = ngx_cpystrn((u_char *) ngx_os_argv[0], (u_char *) "nginx: ",
  17.                     ngx_os_argv_last - ngx_os_argv[0]);
  18.   
  19.     p = ngx_cpystrn(p, (u_char *) title, ngx_os_argv_last - (char *) p);
  20.   
  21. /* 针对Solaris系统,显示的进程名字方式不一样而已,不看了,原理一样的 */
  22. #if (NGX_SOLARIS)
  23.   
  24.     size = 0;
  25.   
  26.     for (i = 0; i < ngx_argc; i++) {
  27.         size += ngx_strlen(ngx_argv[i]) + 1;
  28.     }
  29.   
  30.     if (size > (size_t) ((char *) p - ngx_os_argv[0])) {
  31.   
  32.         /*
  33.          * ngx_setproctitle() is too rare operation so we use
  34.          * the non-optimized copies
  35.          */
  36.   
  37.         p = ngx_cpystrn(p, (u_char *) " (", ngx_os_argv_last - (char *) p);
  38.   
  39.         for (i = 0; i < ngx_argc; i++) {
  40.             p = ngx_cpystrn(p, (u_char *) ngx_argv[i],
  41.                             ngx_os_argv_last - (char *) p);
  42.             p = ngx_cpystrn(p, (u_char *) " ", ngx_os_argv_last - (char *) p);
  43.         }
  44.   
  45.         if (*(p - 1) == ' ') {
  46.             *(p - 1) = ')';
  47.         }
  48.     }
  49.   
  50. #endif
  51.       
  52.     /* 在原始argv和environ的连续内存中,将修改了的进程名字之外的内存全部清零 */
  53.     if (ngx_os_argv_last - (char *) p) {
  54.         ngx_memset(p, NGX_SETPROCTITLE_PAD, ngx_os_argv_last - (char *) p);
  55.     }
  56.   
  57.     ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
  58.                    "setproctitle: \"%s\"", ngx_os_argv[0])



阅读(1433) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~