Uno dei commenti menziona prctl
, ma questo merita davvero una risposta, perché impostando argv[0]
non funzionerà in tutti i casi (non fa nulla sul mio sistema).
Esistono almeno due chiamate di libreria per impostare il nome di un thread in Linux, entrambe limitate a 15 caratteri più il NUL
di terminazione byte:
- specifico per glibc:
pthread_setname_np(...)
dove ilnp
sta per "non-portable", ma potrebbe essere presente su altri sistemi operativi:https://linux.die.net/man/3/pthread_setname_np - Specifico per Linux:
prctl(PR_SET_NAME...)
che è anche non portatile:https://linux.die.net/man/2/prctl
Esempio
Ecco un test dei diversi metodi (senza gestione degli errori):
// 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;
}
Nota la mancanza di output dopo 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]
In natura
Ecco un esempio nel codice di produzione (come sempre, assicurati di prendere nota della licenza quando guardi il codice su GitHub)
Vedi anche
Vedi anche queste domande e risposte:
- https://unix.stackexchange.com/questions/167490/how-can-a-process-appear-to-have-different-name-in-ps-output
- Usare prctl PR_SET_NAME per impostare il nome del processo o del thread?
Penso che dovrebbe funzionare, per illustrare il principio...
#include <stdio.h>
int main(int argc, char *argv[]) {
argv[0][0] = 65;
sleep(10);
}
cambierà il nome e inserirà una "A" al posto della prima lettera. CtrlZ per mettere in pausa, quindi eseguire ps
per vedere il nome cambiato. Non ne ho idea, ma sembra un po' pericoloso, dal momento che alcune cose potrebbero dipendere da argv[0]
.
Inoltre, ho provato a sostituire il puntatore stesso con un'altra stringa; nessun sigaro. Quindi funzionerebbe solo con strcpy
e stringhe più corte o uguali al nome originale.
Potrebbe esserci o meno un modo migliore per questo. Non lo so.
EDIT:soluzione non letterale:se stai effettuando un fork, conosci il PID del bambino (getpid()
nel figlio, risultato di fork()
nel genitore). Emettilo da qualche parte dove puoi leggerlo e uccidi il bambino tramite PID.
un'altra soluzione non letterale:creare collegamenti software all'eseguibile con un altro nome (ln -s a.out kill_this_a.out
), quindi quando esegui, esegui il collegamento. Il nome sarà il nome del collegamento.
Questo è un hack non portatile:
/*
* Sets process title, truncating if there is not enough space,
* rather than causing memory corruption.
*/
void set_title_np(int argc, char **argv, const char *title) {
// calculate available size
size_t space = 0;
for (int i = 0; i < argc; i++) {
size_t length = strlen(argv[i]);
space += length + 1; // because of terminating zero
}
memset(argv[0], '\0', space); // wipe existing args
strncpy(argv[0], title, space - 1); // -1: leave null termination, if title bigger than space
}
Secondo questo commento, prctl(PR_SET_NAME)
riguarda solo il "nome breve" di un thread. Ha lo stesso effetto della scrittura in /proc/self/comm
.
Per modificare il "nome lungo" (/proc/self/cmdline
che è attualmente utilizzato da htop
e ps u
) hai bisogno di qualche brutto hack (che è menzionato in quel commento ma il link è morto). Un esempio di questo tipo di hack può essere trovato nel codice sorgente di Chromium:https://source.chromium.org/chromium/chromium/src/+/master:content/common/set_process_title_linux.cc