您的位置:首页 > 运维架构 > Nginx

[nginx源码分析]set process title

2016-07-30 18:43 489 查看
由于linux argv和environ环境变量内存地址连续,同时argv[0]代表进程name,所以就可以尽可能的用连续的内存空间(起始地址argv[0])来设置进程name

test case如下:

*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>

#define LOGDBG(fmt, args...) do {\
printf("[%s:%d]%s   "fmt"\n", __FILE__, __LINE__, __FUNCTION__, ##args);\
}while(0);

extern char **environ;
int main(int argc, char** argv)
{
uint32_t  i = 0;
uint32_t  env_size = 0;
for (; environ[i];i++)
{
env_size += strlen(environ[i])+1;//\0 char
LOGDBG("environ[i]=%s", environ[i]);
}
LOGDBG("env_size:%u", env_size);

char* env = (char*) malloc(env_size);
char* temp = env;

for(i = 0; environ[i]; i++)
{
snprintf(temp, strlen(environ[i])+1, "%s", environ[i]);
environ[i] = temp;
temp += strlen(environ[i])+1;
}
char* last = environ[i]-1;
argv[1] = NULL;
snprintf(argv[0], last - argv[0], "%s", "set title");

for (i=0; environ[i];i++)
{
LOGDBG("environ[i]=%s", environ[i]);
}
sleep(10);
return 0;
}


testcase 根据的是nginx设置进程为master or worker process的做法,nginx的code 如下:

extern char **environ;

static char *ngx_os_argv_last;

ngx_int_t
ngx_init_setproctitle(ngx_log_t *log)
{
u_char      *p;
size_t       size;
ngx_uint_t   i;

size = 0;

//首先计算出environ需要的内存空间
for (i = 0; environ[i]; i++) {
size += ngx_strlen(environ[i]) + 1;
}

//为environ分配内存空间
p = ngx_alloc(size, log);
if (p == NULL) {
return NGX_ERROR;
}

ngx_os_argv_last = ngx_os_argv[0];

//check连续性
for (i = 0; ngx_os_argv[i]; i++) {
if (ngx_os_argv_last == ngx_os_argv[i]) {
ngx_os_argv_last = ngx_os_argv[i] + ngx_strlen(ngx_os_argv[i]) + 1;
}
}

//copy environ到新分配的内存
for (i = 0; environ[i]; i++) {
if (ngx_os_argv_last == environ[i]) {

size = ngx_strlen(environ[i]) + 1;
ngx_os_argv_last = environ[i] + size;

ngx_cpystrn(p, (u_char *) environ[i], size);
environ[i] = (char *) p;
p += size;
}
}

ngx_os_argv_last--;

return NGX_OK;
}

void
ngx_setproctitle(char *title)
{
u_char     *p;

#if (NGX_SOLARIS)

ngx_int_t   i;
size_t      size;

#endif

//先把argv数组的第二个节点置为空
ngx_os_argv[1] = NULL;

//copy
p = ngx_cpystrn((u_char *) ngx_os_argv[0], (u_char *) "nginx: ",
ngx_os_argv_last - ngx_os_argv[0]);

p = ngx_cpystrn(p, (u_char *) title, ngx_os_argv_last - (char *) p);

#if (NGX_SOLARIS)

size = 0;

for (i = 0; i < ngx_argc; i++) {
size += ngx_strlen(ngx_argv[i]) + 1;
}

if (size > (size_t) ((char *) p - ngx_os_argv[0])) {

/*
* ngx_setproctitle() is too rare operation so we use
* the non-optimized copies
*/

p = ngx_cpystrn(p, (u_char *) " (", ngx_os_argv_last - (char *) p);

for (i = 0; i < ngx_argc; i++) {
p = ngx_cpystrn(p, (u_char *) ngx_argv[i],
ngx_os_argv_last - (char *) p);
p = ngx_cpystrn(p, (u_char *) " ", ngx_os_argv_last - (char *) p);
}

if (*(p - 1) == ' ') {
*(p - 1) = ')';
}
}

#endif

if (ngx_os_argv_last - (char *) p) {
ngx_memset(p, NGX_SETPROCTITLE_PAD, ngx_os_argv_last - (char *) p);
}

ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
"setproctitle: \"%s\"", ngx_os_argv[0]);
}

#endif /* NGX_SETPROCTITLE_USES_ENV */


也是先copy environ到新的地址空间,用连续的内存空间来设置进程title
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  nginx 源码 linux