恰好看到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的空間的釋放。