nginx 設置進程title

恰好看到nginx設置進程title的源碼,所以作一些總結。 html

linux進程實際是以argv[0]處的值來做爲進程的title的,所以若須要修改進程的title只須要修改argv[0]處的值便可。linux

簡單的方法就是直接將想要設置的title複製給argv[0]便可,以下示:nginx

   1: #include <stdio.h>
   2: #include <stdlib.h>
   3: #include <string.h>
   4: #include <unistd.h>
   5:  
   6: extern char** environ;
   7:  
   8: int main(int argc, char* argv[])
   9: {
  10:     char s_title[] = "ymc title for simple way!";
  11:     size_t i_size = strlen(s_title);
  12:  
  13:     memcpy(argv[0], s_title, i_size);
  14:     argv[0][i_size] = '\0';
  15:     
  16:     while(1){
  17:         system("ps -ef|awk '$8 ~ /ymc/ {print $0}'");
  18:         sleep(10);
  19:     }
  20:  
  21:     return 0;
  22: }

運行結果爲:app

[root@localhost prc_title]# ./prc_title_simple 
root 19062 14675 0 20:17 pts/0 00:00:00 ymc title for simple way!
root 19062 14675 0 20:17 pts/0 00:00:00 ymc title for simple way!

可是這種方式是以破壞性的方式,進程的進程title的修改。因爲程序的參數存儲空間的後面緊跟的就是環境變量的存儲位置,在不考慮參數的破壞性的狀況下less

過長的title也會損壞環境變量environ的值。所以在nginx中,是將環境變量進行移位存儲處理的。下面是nginx處理進程設置title的思路。ide

/*
* To change the process title in Linux and Solaris we have to set argv[1]
* to NULL and to copy the title to the same place where the argv[0] points to.
* However, argv[0] may be too small to hold a new title. Fortunately, Linux
* and Solaris store argv[] and environ[] one after another. So we should
* ensure that is the continuous memory and then we allocate the new memory
* for environ[] and copy it. After this we could use the memory starting
* from argv[0] for our process title.
*
* The Solaris's standard /bin/ps does not show the changed process title.
* You have to use "/usr/ucb/ps -w" instead. Besides, the UCB ps dos not
* show a new title if its length less than the origin command line length.
* To avoid it we append to a new title the origin command line in the
* parenthesis.
*/

而後因爲nginx中考慮多進程的狀況,所以他會在初始化時就完成environ的遷移。下面是初始化函數函數

   1: //指向環境變量,默認的
   2: extern char **environ;
   3: //指向以前的用於存放參數及環境變量的空間的最後位置。
   4: static char *ngx_os_argv_last;
   5:  
   6: ngx_int_t
   7: ngx_init_setproctitle(ngx_log_t *log)
   8: {
   9:     u_char      *p;
  10:     size_t       size;
  11:     ngx_uint_t   i;
  12:  
  13:     size = 0;
  14:     //計算環境變量所用的總的空間的大小,而後以申請足夠的空間用於存放環境變量
  15:     for (i = 0; environ[i]; i++) {
  16:         size += ngx_strlen(environ[i]) + 1;
  17:     }
  18:     //爲環境就是分配空間
  19:     p = ngx_alloc(size, log);
  20:     if (p == NULL) {
  21:         return NGX_ERROR;
  22:     }
  23:     //下面開始計算前面用於存放環境變量的最後位置
  24:     ngx_os_argv_last = ngx_os_argv[0];
  25:     //首先計算參數的最後位置
  26:     for (i = 0; ngx_os_argv[i]; i++) {
  27:         if (ngx_os_argv_last == ngx_os_argv[i]) {
  28:             ngx_os_argv_last = ngx_os_argv[i] + ngx_strlen(ngx_os_argv[i]) + 1;
  29:         }
  30:     }
  31:     //再計算環境變量佔用的最後位置,並完成環境變量的拷貝
  32:     for (i = 0; environ[i]; i++) {
  33:         if (ngx_os_argv_last == environ[i]) {
  34:  
  35:             size = ngx_strlen(environ[i]) + 1;
  36:             ngx_os_argv_last = environ[i] + size;
  37:  
  38:             ngx_cpystrn(p, (u_char *) environ[i], size);
  39:             environ[i] = (char *) p;
  40:             p += size;
  41:         }
  42:     }
  43:  
  44:     ngx_os_argv_last--;
  45:  
  46:     return NGX_OK;
  47: }

而後是具體的設置title的函數oop

   1: void
   2: ngx_setproctitle(char *title)
   3: {
   4:     u_char     *p;
   5:  
   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:     //設置title,
  15:     p = ngx_cpystrn((u_char *) ngx_os_argv[0], (u_char *) "nginx: ",
  16:                     ngx_os_argv_last - ngx_os_argv[0]);
  17:  
  18:     p = ngx_cpystrn(p, (u_char *) title, ngx_os_argv_last - (char *) p);
  19:  
  20: #if (NGX_SOLARIS)
  21:  
  22:     size = 0;
  23:  
  24:     for (i = 0; i < ngx_argc; i++) {
  25:         size += ngx_strlen(ngx_argv[i]) + 1;
  26:     }
  27:  
  28:     if (size > (size_t) ((char *) p - ngx_os_argv[0])) {
  29:  
  30:         /*
  31:          * ngx_setproctitle() is too rare operation so we use
  32:          * the non-optimized copies
  33:          */
  34:  
  35:         p = ngx_cpystrn(p, (u_char *) " (", ngx_os_argv_last - (char *) p);
  36:  
  37:         for (i = 0; i < ngx_argc; i++) {
  38:             p = ngx_cpystrn(p, (u_char *) ngx_argv[i],
  39:                             ngx_os_argv_last - (char *) p);
  40:             p = ngx_cpystrn(p, (u_char *) " ", ngx_os_argv_last - (char *) p);
  41:         }
  42:  
  43:         if (*(p - 1) == ' ') {
  44:             *(p - 1) = ')';
  45:         }
  46:     }
  47:  
  48: #endif
  49:  
  50:     if (ngx_os_argv_last - (char *) p) {
  51:         ngx_memset(p, NGX_SETPROCTITLE_PAD, ngx_os_argv_last - (char *) p);
  52:     }
  53:  
  54:     ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
  55:                    "setproctitle: \"%s\"", ngx_os_argv[0]);
  56: }

最後就是根據nginx的思想的一個簡單修改title的示例:ui

   1: #include <stdio.h>
   2: #include <stdlib.h>
   3: #include <string.h>
   4: #include <unistd.h>
   5:  
   6: extern char** environ;
   7:  
   8: void my_initproctitle(char* argv[], char** last);
   9: void my_setproctitle(char* argv[], char** last, char* title);
  10:  
  11: int main(int argc, char* argv[])
  12: {
  13:     char s_title[] = "ymc title ymc title";
  14:     char* p_last = NULL;
  15:  
  16:    my_initproctitle(argv, &p_last);
  17:    my_setproctitle(argv, &p_last, s_title);
  18:  
  19:     while(1)
  20:     {
  21:         system("ps -ef|awk '$8 ~ /ymc/ {print $0}'");
  22:         sleep(10);
  23:     }
  24:  
  25:     return 0;
  26: }
  27:  
  28: void my_initproctitle(char* argv[], char** last)
  29: {
  30:     int i = 0;
  31:     char* p_tmp = NULL;
  32:     size_t i_size = 0;
  33:  
  34:     for(i = 0; environ[i]; i++){
  35:         i_size += strlen(environ[i]) + 1;
  36:     }
  37:  
  38:     p_tmp = malloc(i_size);
  39:     if(p_tmp == NULL){
  40:         return ;
  41:     }
  42:  
  43:     *last = argv[0];
  44:     for(i = 0; argv[i]; i++){
  45:         *last += strlen(argv[i]) + 1;
  46:     }
  47:  
  48:     for(i = 0; environ[i]; i++){
  49:         i_size = strlen(environ[i]) + 1;
  50:         *last += i_size;
  51:  
  52:         strncpy(p_tmp, environ[i], i_size);
  53:         environ[i] = p_tmp;
  54:         p_tmp += i_size;
  55:     }
  56:  
  57:     (*last)--;
  58:  
  59:     return ;
  60:  
  61: }
  62:  
  63: void my_setproctitle(char* argv[], char** last, char* title)
  64: {
  65:     char* p_tmp = NULL;
  66:     /* argv[1] = NULL; */
  67:  
  68:     p_tmp = argv[0];
  69:     /* memset(p_tmp, 0, *last - p_tmp); */
  70:     strncpy(p_tmp, title, *last - p_tmp);
  71:  
  72:     return ;
  73: }

運行結果:this

[root@localhost prc_title]# ./prc_title
root 19507 14675 0 20:33 pts/0 00:00:00 ymc title ymc title

這裏還有個問題就是沒考慮新的存儲environ的空間的釋放。

轉載請註明出處:http://www.cnblogs.com/doop-ymc/p/3432184.html

相關文章
相關標籤/搜索