Подтвердить что ты не робот

Изменить имя процесса в Linux

Я нахожусь в Linux, и я форкирую/выполняю новый процесс из своего приложения C spawn. Можно ли также изменить именование этих новых дочерних процессов?

Я хочу иметь возможность идентифицировать начавшийся процесс в случае, если что-то пойдет не так, и мне нужно его убить вручную. В настоящее время все они имеют одинаковое имя.

4b9b3361

Ответ 1

Я думаю, что это должно сработать, чтобы проиллюстрировать принцип...

#include <stdio.h>

int main(int argc, char *argv[]) {
  argv[0][0] = 65;
  sleep(10);
}

изменит имя и поместит вместо буквы "А" вместо первой буквы. CtrlZ для приостановки, затем запустите ps, чтобы увидеть, как изменилось имя. У меня нет подсказки, но это кажется несколько опасным, поскольку некоторые вещи могут зависеть от argv[0].

Кроме того, я попытался заменить сам указатель на другую строку; нет сигары. Таким образом, это будет работать только с strcpy и строками короче или равными исходному имени.

Там может быть и не лучше. Я не знаю.

EDIT: нелитеративное решение: если вы используете forking, вы знаете дочерний PID (getpid() у ребенка, результат fork() в родительском). Просто выведите его где-нибудь, где вы можете его прочитать, и убить ребенка с помощью PID.

другое нелитеративное решение: сделайте программные ссылки для исполняемого файла с другим именем (ln -s a.out kill_this_a.out), затем, когда вы выполните exec, выполните ссылку. Имя будет именем ссылки.

Ответ 2

В одном из комментариев упоминается prctl, но это действительно заслуживает отдельного ответа, потому что установка argv[0] не будет работать во всех случаях (она ничего не делает в моей системе).

Существует как минимум два библиотечных вызова для установки имени потока в Linux, оба ограничены 15 символами плюс завершающий байт NUL:

  1. специфично для glibc: pthread_setname_np(...) где np означает "непереносимый", но это может присутствовать в некоторых других ОС: https://linux.die.net/man/3/pthread_setname_np
  2. Для Linux: prctl(PR_SET_NAME...) который также является prctl(PR_SET_NAME...): https://linux.die.net/man/2/prctl

пример

Вот тест различных методов (без обработки ошибок):

// gcc pstest.c -o pstest -O2 -Wall -Wextra -Werror -Wno-unused -Wno-unused-result -std=gnu99 -pthread -D_GNU_SOURCE 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/prctl.h>

int main(int argc, char *argv[])
{
    puts("Initial ps output:");
    system("ps | grep pstest");

    puts("\npthread_setname_np");
    pthread_setname_np(pthread_self(), "setname");
    system("ps | grep setname");

    puts("\nprctl");
    prctl(PR_SET_NAME, (unsigned long)"prctl", 0, 0, 0);
    system("ps | grep prctl");

    puts("\nargv[0]");
    argv[0] = "argv0";
    system("ps | grep argv0");

    return 0;
}

Обратите внимание на отсутствие вывода после argv[0]:

./pstest
Initial ps output:
17169 pts/0    00:00:00 pstest

pthread_setname_np
17169 pts/0    00:00:00 setname

prctl
17169 pts/0    00:00:00 prctl

argv[0]

В дикой природе

Вот пример в рабочем коде (как всегда, обратите внимание на лицензию при просмотре кода на GitHub)

Смотрите также

Смотрите также эти вопросы и ответы:

Ответ 3

Согласно этому комментарию, prctl(PR_SET_NAME) влияет только на "короткое имя" потока. Это имеет тот же эффект, что и запись в /proc/self/comm.

Чтобы изменить "длинное имя" (/proc/self/cmdline, которое на самом деле используется htop и ps u), вам нужен некрасивый хак (который упоминается в этом комментарии, но ссылка мертва). Пример такого взлома можно найти в исходном коде Chromium: https://cs.chromium.org/chromium/src/services/service_manager/embedder/set_process_title_linux.cc?sq=package:chromium&g=0

Ответ 4

Нижеприведенный пример кода изменит имя процесса на "Тестирование".

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    int main (int argc, char *argv[]) {
    char* temp = (char*) malloc (20);
    strcpy(temp, "Testing");
    temp[7] = 0;
    printf("Argv[0] --> %s\n", argv[0]);
    argv[0] = temp;
    printf("Argv[0] --> %s\n", argv[0]);    
    return 0;
    }

Вывод программы выше:

./a.out

Argv [0] → ./a.out

Argv [0] → Тестирование

Аргус [0] содержит имя процесса.