Linux下修改进程名

最近用C/C++写个mysql的进程池,每个子进程负责处理请求,而master主进程则负责监控哪个子进程挂掉了,发现有挂掉的就再创建一个顶上。这个时候就需要知道多个进程中哪个是master进程,通常来说是进程号最小的,如果能够有不一样的进程名就太好了,就像nginx那样。所以研究了一把如何修改进程的名称。

c语言的入口函数main如果参数写全了,就是如下这样:

int main(int argc, const char* argv[], const char* envp[])

argv是执行参数,envp是执行环境,这些信息在内存中均为连续排布,举例如下:

其实环境变量也是全局可引用的,下面例子代码中的environ和envp是一个地址值。写个例子程序:

extern char **environ;
int main(int argc, const char* argv[], const char* envp[])
{
    int i = 0;
    for (;argv[i]; ++i) {
        cout << argv[i] << endl;
    }
    cout << "----------------------" << endl;
    ++i;
    for (;argv[i]; ++i) {
        cout << argv[i] << endl;
    }
    cout << "----------------------" << endl;
    cout << environ[0] << endl;

    cout << "----------------------" << endl;
    cout << envp[0] << endl;
    cout << "----------------------" << endl;

    return 0;
}

修改进程名有标准函数:prctl(PR_SET_NAME, arg2),但是顶多只能有16个字节长,需要\0结尾。而且prctl只是修改了进程状态名,而不是修改了原始命令,所以还得必须使用ps -a来查看,而不是ps a,注意此两种ps带参数的不同。

修改进程名更直接的办法就是直接修改argv[0]指向内存的内容,不过修改后的进程title不能超过原来长度。举个例子:

int main(int argc, const char* argv[], const char* envp[])
{
    char *tmp = (char*)(argv[0]);
    tmp[0] = 'z';
    sleep(100);
    return 0;
}

参考nginx的源码,如果想修改后的进程名长度不受限制,需要腾挪一下环境变量,因为环境变量在程序执行过程中还是会用到的,而执行参数就无所谓了。所以分为两步:

1. 分配内存,拷贝envp[0]所指向的内存内容,将envp中的指针均指向这个新开辟的内存

2. 将原来的argv[0]和envp[0]所指向的连续空间都清零,这块空间就是可用来设置新进程名的空间了,安全起见设置argv[1] = NULL

例子代码:

int main(int argc, const char* argv[], const char* envp[])
{
    int i;
    for (i = 0; envp[i]; ++i);
    const char *p = envp[i-1] + strlen(envp[i-1]) + 1;

    //move environ info
    char **ptrs = (char**)malloc(sizeof(char*) * i);
    ptrs[0] = (char*)malloc(p - envp[0]);
    memcpy(ptrs[0], envp[0], p - envp[0]);
    //copy ptr address
    for (int j = 1; j < i; ++j) {
        ptrs[j] = ptrs[j-1] + (envp[j] - envp[j-1]);
    }
    for (int j = 0; j < i; ++j) {
        envp[j] = ptrs[j];
    }
    free((void*)ptrs);

    //setting new title
    memset((char*)argv[0], 0, p - argv[0]);
    snprintf((char*)argv[0], p - argv[0], "show my newest name");

    //done
    for (int i = 0; envp[i]; ++i) {
        cout << envp[i] << endl;
    }

    sleep(100);
    return 0;
}

还可以只清零,不设置新的进程名,这样就得到一个无名进程,ps等各种命令查不到,木马专用技术。

发表于 2018年02月08日 14:42   修改于 2023年04月24日 23:50   评论:1   阅读:4225  



回到顶部

首页 | 关于我 | 关于本站 | 站内留言 | rss
python logo   django logo   tornado logo