刚好看到nginx设置进程title的源码,因此做一些总结。
linux进程实际是以argv[0]处的值来作为进程的title的,因此若需要修改进程的title只需要修改argv[0]处的值即可。
简单的方法就是直接将想要设置的title复制给argv[0]即可,如下示:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>5:char** environ;7:char* argv[])9: {;11: size_t i_size = strlen(s_title);12:13: memcpy(argv[0], s_title, i_size);'\0';15:while(1){);18: sleep(10);19: }20:return 0;22: }
运行结果为:
[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的修改。由于程序的参数存储空间的后面紧跟的就是环境变量的存储位置,在不考虑参数的破坏性的情况下
过长的title也会损坏环境变量environ的值。因此在nginx中,是将环境变量进行移位存储处理的。下面是nginx处理进程设置title的思路。
/*
* 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的迁移。下面是初始化函数
//指向环境变量,默认的
char **environ;
//指向之前的用于存放参数及环境变量的空间的最后位置。
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;
//计算环境变量所用的总的空间的大小,然后以申请足够的空间用于存放环境变量
for (i = 0; environ[i]; i++) {
16: size += ngx_strlen(environ[i]) + 1;
17: }
//为环境就是分配空间
19: p = ngx_alloc(size, log);
if (p == NULL) {
return NGX_ERROR;
22: }
//下面开始计算前面用于存放环境变量的最后位置
24: 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]) {
28: ngx_os_argv_last = ngx_os_argv[i] + ngx_strlen(ngx_os_argv[i]) + 1;
29: }
30: }
//再计算环境变量占用的最后位置,并完成环境变量的拷贝
for (i = 0; environ[i]; i++) {
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);
char *) p;
40: p += size;
41: }
42: }
43:
44: ngx_os_argv_last--;
45:
return NGX_OK;
47: }
然后是具体的设置title的函数
void
char *title)
3: {
4: u_char *p;
5:
#if (NGX_SOLARIS)
7:
8: ngx_int_t i;
9: size_t size;
10:
#endif
12:
13: ngx_os_argv[1] = NULL;
//设置title,
,
16: ngx_os_argv_last - ngx_os_argv[0]);
17:
char *) p);
19:
#if (NGX_SOLARIS)
21:
22: size = 0;
23:
for (i = 0; i < ngx_argc; i++) {
25: size += ngx_strlen(ngx_argv[i]) + 1;
26: }
27:
char *) p - ngx_os_argv[0])) {
29:
/*
* ngx_setproctitle() is too rare operation so we use
* the non-optimized copies
*/
34:
char *) p);
36:
for (i = 0; i < ngx_argc; i++) {
38: p = ngx_cpystrn(p, (u_char *) ngx_argv[i],
char *) p);
char *) p);
41: }
42:
' ') {
')';
45: }
46: }
47:
#endif
49:
char *) p) {
char *) p);
52: }
53:
54: ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
, ngx_os_argv[0]);
56: }
最后就是根据nginx的思想的一个简单修改title的示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
5:
char** environ;
7:
char** last);
char* title);
10:
char* argv[])
12: {
;
char* p_last = NULL;
15:
16: my_initproctitle(argv, &p_last);
17: my_setproctitle(argv, &p_last, s_title);
18:
while(1)
20: {
);
22: sleep(10);
23: }
24:
return 0;
26: }
27:
char** last)
29: {
int i = 0;
char* p_tmp = NULL;
32: size_t i_size = 0;
33:
for(i = 0; environ[i]; i++){
35: i_size += strlen(environ[i]) + 1;
36: }
37:
38: p_tmp = malloc(i_size);
if(p_tmp == NULL){
return ;
41: }
42:
43: *last = argv[0];
for(i = 0; argv[i]; i++){
45: *last += strlen(argv[i]) + 1;
46: }
47:
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:
return ;
60:
61: }
62:
char* title)
64: {
char* p_tmp = NULL;
/* argv[1] = NULL; */
67:
68: p_tmp = argv[0];
/* memset(p_tmp, 0, *last - p_tmp); */
70: strncpy(p_tmp, title, *last - p_tmp);
71:
return ;
73: }
运行结果:
[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