Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux-如何在C中更改分叉进程的信息_C_Linux_Gcc_Fork - Fatal编程技术网

Linux-如何在C中更改分叉进程的信息

Linux-如何在C中更改分叉进程的信息,c,linux,gcc,fork,C,Linux,Gcc,Fork,标题听起来可能有点奇怪,因为ps aux我看到: root 20953 0.0 0.0 9528 1280 ? Ss Apr28 0:07 sendmail: accepting connections 其中“接受连接”类似于sendmail流程的标题。它不是参数,因为cat/proc/20953/cmdline返回sendmail:accepting connections(空格而不是0x00): /proc fs中的参数用空字节分隔: # cat /

标题听起来可能有点奇怪,因为
ps aux
我看到:

root     20953  0.0  0.0   9528  1280 ?        Ss   Apr28   0:07 sendmail: accepting connections
其中“接受连接”类似于sendmail流程的标题。它不是参数,因为
cat/proc/20953/cmdline
返回
sendmail:accepting connections
(空格而不是0x00):

/proc fs中的参数用空字节分隔:

# cat /proc/26511/cmdline |hexdump -C
00000000  2f 62 69 6e 2f 62 61 73  68 00 2f 77 65 62 72 6f  |/bin/bash./webro|
00000010  6f 74 2f 70 72 6f 72 61  69 6c 2f 73 63 72 69 70  |ot/prorail/scrip|
00000020  74 73 2f 73 79 6e 63 6c  6f 6f 70 2e 73 68 00     |ts/syncloop.sh.|
0000002f

因此,当我在C中使用fork()时,如何设置此进程信息,以便识别哪个进程?

sendmail有多种方法,具体取决于系统。请参阅源代码中sendmail/conf.C中的setproctitle:

#define SPT_NONE        0       /* don't use it at all */
#define SPT_REUSEARGV   1       /* cover argv with title information */
#define SPT_BUILTIN     2       /* use libc builtin */
#define SPT_PSTAT       3       /* use pstat(PSTAT_SETCMD, ...) */
#define SPT_PSSTRINGS   4       /* use PS_STRINGS->... */
#define SPT_SYSMIPS     5       /* use sysmips() supported by NEWS-OS 6 */
#define SPT_SCO         6       /* write kernel u. area */
#define SPT_CHANGEARGV  7       /* write our own strings into argv[] */
有关详细信息,请参阅conf.c中的setproctitle例程。

我找到了答案,尽管问题不是同一个问题。所有学分都应该交给

#包括
#包括
int main(int argc,字符**argv)
{
strcpy(argv[0],“你好,世界!”);
睡眠(10);
返回0;
}
在本文中:作者解释了如何更改流程标题。我猜setproctitle是的,所以他尝试在linux上实现它。下面是来自

我还没有测试过。我还没有检查它是否使用库中的其他函数,因此代码可能不完整。请随意测试它并留下一个结果

/*
 * Sets the process title to the specified title. Note that this may fail if
 * the kernel doesn't support PR_SET_MM_MAP (kernels <3.18).
 */
int setproctitle(char *title)
{
    static char *proctitle = NULL;
    char buf[2048], *tmp;
    FILE *f;
    int i, len, ret = 0;

    /* We don't really need to know all of this stuff, but unfortunately
     * PR_SET_MM_MAP requires us to set it all at once, so we have to
     * figure it out anyway.
     */
    unsigned long start_data, end_data, start_brk, start_code, end_code,
            start_stack, arg_start, arg_end, env_start, env_end,
            brk_val;
    struct prctl_mm_map prctl_map;

    f = fopen_cloexec("/proc/self/stat", "r");
    if (!f) {
        return -1;
    }

    tmp = fgets(buf, sizeof(buf), f);
    fclose(f);
    if (!tmp) {
        return -1;
    }

    /* Skip the first 25 fields, column 26-28 are start_code, end_code,
     * and start_stack */
    tmp = strchr(buf, ' ');
    for (i = 0; i < 24; i++) {
        if (!tmp)
            return -1;
        tmp = strchr(tmp+1, ' ');
    }
    if (!tmp)
        return -1;

    i = sscanf(tmp, "%lu %lu %lu", &start_code, &end_code, &start_stack);
    if (i != 3)
        return -1;

    /* Skip the next 19 fields, column 45-51 are start_data to arg_end */
    for (i = 0; i < 19; i++) {
        if (!tmp)
            return -1;
        tmp = strchr(tmp+1, ' ');
    }

    if (!tmp)
        return -1;

    i = sscanf(tmp, "%lu %lu %lu %*u %*u %lu %lu",
        &start_data,
        &end_data,
        &start_brk,
        &env_start,
        &env_end);
    if (i != 5)
        return -1;

    /* Include the null byte here, because in the calculations below we
     * want to have room for it. */
    len = strlen(title) + 1;

    proctitle = realloc(proctitle, len);
    if (!proctitle)
        return -1;

    arg_start = (unsigned long) proctitle;
    arg_end = arg_start + len;

    brk_val = syscall(__NR_brk, 0);

    prctl_map = (struct prctl_mm_map) {
        .start_code = start_code,
        .end_code = end_code,
        .start_stack = start_stack,
        .start_data = start_data,
        .end_data = end_data,
        .start_brk = start_brk,
        .brk = brk_val,
        .arg_start = arg_start,
        .arg_end = arg_end,
        .env_start = env_start,
        .env_end = env_end,
        .auxv = NULL,
        .auxv_size = 0,
        .exe_fd = -1,
    };

    ret = prctl(PR_SET_MM, PR_SET_MM_MAP, (long) &prctl_map, sizeof(prctl_map), 0);
    if (ret == 0)
        strcpy((char*)arg_start, title);
    else
        INFO("setting cmdline failed - %s", strerror(errno));

    return ret;
}
/*
*将流程标题设置为指定的标题。请注意,如果

*内核不支持PR\u SET\u MM\u映射(内核可能与我的问题有点不同,尽管那里有我问题的答案。我问如何用C来做。答案被接受并不是我想要的答案。我将复制正确答案,并将关闭它的决定留给版主。感谢链接!这将覆盖其他内容。我找到了另一个答案解决方案-我将在单独的答案中发布
#include <string.h>
#include <unistd.h>

int main(int argc, char** argv)
{
    strcpy(argv[0], "Hello, world!");
    sleep(10);
    return 0;
}
/*
 * Sets the process title to the specified title. Note that this may fail if
 * the kernel doesn't support PR_SET_MM_MAP (kernels <3.18).
 */
int setproctitle(char *title)
{
    static char *proctitle = NULL;
    char buf[2048], *tmp;
    FILE *f;
    int i, len, ret = 0;

    /* We don't really need to know all of this stuff, but unfortunately
     * PR_SET_MM_MAP requires us to set it all at once, so we have to
     * figure it out anyway.
     */
    unsigned long start_data, end_data, start_brk, start_code, end_code,
            start_stack, arg_start, arg_end, env_start, env_end,
            brk_val;
    struct prctl_mm_map prctl_map;

    f = fopen_cloexec("/proc/self/stat", "r");
    if (!f) {
        return -1;
    }

    tmp = fgets(buf, sizeof(buf), f);
    fclose(f);
    if (!tmp) {
        return -1;
    }

    /* Skip the first 25 fields, column 26-28 are start_code, end_code,
     * and start_stack */
    tmp = strchr(buf, ' ');
    for (i = 0; i < 24; i++) {
        if (!tmp)
            return -1;
        tmp = strchr(tmp+1, ' ');
    }
    if (!tmp)
        return -1;

    i = sscanf(tmp, "%lu %lu %lu", &start_code, &end_code, &start_stack);
    if (i != 3)
        return -1;

    /* Skip the next 19 fields, column 45-51 are start_data to arg_end */
    for (i = 0; i < 19; i++) {
        if (!tmp)
            return -1;
        tmp = strchr(tmp+1, ' ');
    }

    if (!tmp)
        return -1;

    i = sscanf(tmp, "%lu %lu %lu %*u %*u %lu %lu",
        &start_data,
        &end_data,
        &start_brk,
        &env_start,
        &env_end);
    if (i != 5)
        return -1;

    /* Include the null byte here, because in the calculations below we
     * want to have room for it. */
    len = strlen(title) + 1;

    proctitle = realloc(proctitle, len);
    if (!proctitle)
        return -1;

    arg_start = (unsigned long) proctitle;
    arg_end = arg_start + len;

    brk_val = syscall(__NR_brk, 0);

    prctl_map = (struct prctl_mm_map) {
        .start_code = start_code,
        .end_code = end_code,
        .start_stack = start_stack,
        .start_data = start_data,
        .end_data = end_data,
        .start_brk = start_brk,
        .brk = brk_val,
        .arg_start = arg_start,
        .arg_end = arg_end,
        .env_start = env_start,
        .env_end = env_end,
        .auxv = NULL,
        .auxv_size = 0,
        .exe_fd = -1,
    };

    ret = prctl(PR_SET_MM, PR_SET_MM_MAP, (long) &prctl_map, sizeof(prctl_map), 0);
    if (ret == 0)
        strcpy((char*)arg_start, title);
    else
        INFO("setting cmdline failed - %s", strerror(errno));

    return ret;
}