Linux 进程名修改

/* 进程名修改 */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

/*
知识补充:
    Linux C中environ 变量是一个char** 类型,存储着系统的环境变量。
    因为environ是一个全局的外部变量,所以切记使用前要用extern关键字进行声明,然后在使用。
    unistd.h头文件中声明了这个变量,所以也可以将unistd.h进行include,这个时候就不用再对environ进行extern声明了(应为unistd.h中已经声明了),
    要注意的问题是,在unistd.h中声明environ的地方使用了条件编译,编译的条件就是#ifdef __USE_GNU,LinuxC中默认没有定义这个宏,
    所以要在#include <unistd.h>之前加上#define __USE_GNU
*/

extern char** environ;

/*
知识补充:
    在linux上修改进程名需要设置argv[1]为NULL,并且拷贝进程名到argv[0]指向的内存空间上。
    然而argv[0]的内存空间可能不够存放新的进程名,幸运的是Linux存储argv[] and environ[]用的是一块连续内存。
    因此我们可以分配一块新内存拷贝environ[],之后我们就可以安全的拷贝进程名到argv[0]上了。
*/

static char* gtc_os_argv_last;

int gtc_init_setproctitle(char* argv[])
{
    int ret = 0;

    /*
    设计说明:
        初始化是为了保证修改进程名的安全,
        gtc_os_argv_last变量实际上是指向当前进程可以修改进程名的最大长度
    */
    unsigned char    * p;
    size_t             size;
    unsigned int       i;

    size = 0;

    // 计算环境变量的长度
    for (i = 0; environ[i]; i++) {
        size += strlen(environ[i]) + 1;
    }

    // 创建内存,用来保存当前进程的环境变量
    p = calloc(1, size);
    if (NULL == p)
    {
        ret = -1;
        return ret;
    }

    // 从命令行参数开始计数
    gtc_os_argv_last = argv[0];

    for (i = 0; argv[i]; i++) {
        // 遍历命令行参数
        if (gtc_os_argv_last == argv[i]) {
            // gtc_os_argv_last指向下一个命令行参数
            gtc_os_argv_last = argv[i] + strlen(argv[i]) + 1;
        }
    }

    // 遍历环境变量
    for (i = 0; environ[i]; i++) {
        if (gtc_os_argv_last == environ[i]) {

            size = strlen(environ[i]) + 1;
            gtc_os_argv_last = environ[i] + size;

            strncpy((char*)p, environ[i], size);
            // 修改environ的元素指向,原来environ的元素可能会被 gtc_setproctitle 函数破坏
            environ[i] = (char*)p;
            p += size;
        }
    }

    // 保留最后一个字节为'\0'
    gtc_os_argv_last--;

    return ret;
}


void gtc_setproctitle(const char* title, char* argv[])
{
    argv[1] = NULL;

    // 修改进程名
    strncpy(argv[0], title, gtc_os_argv_last - argv[0]);

}

int main(int argc, char* argv[])
{
    const char* title = "Blue bird";
    // 初始化
    gtc_init_setproctitle(argv);

    // 等待输入
    printf("Please enter a character to change the process name.\n");
    getchar();

    // 修改进程名
    gtc_setproctitle(title, argv);

    printf("The process name has changed, please observe.\n");
    getchar();

    return 0;
}

 

/*
    知识补充:
        ngx_os_argv, environ 是一个字符串数组,数组元素是字符串指针
        这两个变量的元素指向的内存空间是连续的
        ngx_os_argv, environ 这两个变量的内存空间不是连续的
        
    */

    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]) {
            ngx_os_argv_last = ngx_os_argv[i] + ngx_strlen(ngx_os_argv[i]) + 1;
        }
    }

    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;
        }
    }
    
    // 保存最后一个字符,存放'\0'
    ngx_os_argv_last--;

 

posted on 2023-02-17 20:43  寒魔影  阅读(683)  评论(0编辑  收藏  举报

导航