Prima di tutto, so che domande simili sono state poste, ma le risposte fornite non sono state di grande aiuto finora (raccomandano tutte una delle seguenti opzioni).Recupero nomi di processi in esecuzione
Ho un'applicazione utente che deve determinare se un particolare processo è in esecuzione. Ecco quello che so sul processo:
- Il nome
- L'utente (
root
) - E dovrebbe già essere in esecuzione, in quanto si tratta di un LaunchDaemon, il che significa
- Il suo processo genitore dovrebbe essere
launchd
(pid 1)
Ho provato diversi modi per ottenere questo, ma nessuno ha funzionato finora. Ecco quello che ho provato:
Esecuzione
ps
e verificando l'output. Funziona, ma è lento (fork
/exec
è costoso) e mi piacerebbe che fosse il più veloce possibile.Utilizzo della funzione listed here. Funziona anche, ma il modo in cui dicono di recuperare il nome del processo (accesso a
kp_proc.p_comm
da ciascuna strutturakinfo_proc
) è difettoso. La risultantechar*
contiene solo i primi 16 caratteri del nome del processo, che può essere visto nella definizione delkp_proc
struttura:#define MAXCOMLEN 16 //defined in param.h struct extern_proc { //defined in proc.h ...snip... char p_comm[MAXCOMLEN+1]; ...snip... };
Utilizzando libProc.h per recuperare le informazioni di processo:
pid_t pids[1024]; int numberOfProcesses = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0); proc_listpids(PROC_ALL_PIDS, 0, pids, sizeof(pids)); for (int i = 0; i < numberOfProcesses; ++i) { if (pids[i] == 0) { continue; } char name[1024]; proc_name(pids[i], name, sizeof(name)); printf("Found process: %s\n", name); }
questo funziona , tranne che ha lo stesso difetto di
GetBSDProcessList
. Viene restituita solo la prima parte del nome del processo.Utilizzando la ProcessManager function in carbonio:
ProcessSerialNumber psn; psn.lowLongOfPSN = kNoProcess; psn.highLongOfPSN = 0; while (GetNextProcess(&psn) == noErr) { CFStringRef procName = NULL; if (CopyProcessName(&psn, &procName) == noErr) { NSLog(@"Found process: %@", (NSString *)procName); } CFRelease(procName); }
questo non funziona. Restituisce solo i processi registrati con il WindowServer (o qualcosa del genere). In altre parole, restituisce solo app con interfaccia utente e solo per l'utente corrente.
Non riesco a utilizzare
-[NSWorkspace launchedApplications]
, poiché questo deve essere compatibile con 10.5. Inoltre, questo restituisce solo le informazioni sulle applicazioni visualizzate nel Dock per l'utente corrente.
So che è possibile per recuperare il nome dei processi in esecuzione (poiché ps
può farlo), ma la domanda è: "Posso farlo senza sborsare e exec'ing ps
?".
Qualche suggerimento?
EDIT
Dopo aver fatto una ricerca molto di più, sono stato in grado di trovare un modo per farlo. Ho trovato this SO question, che si riferiva a this C file in a python module. Ciò è stato davvero utile nel tentativo di utilizzare i valori KERN_PROCARGS
in una chiamata sysctl
.
Tuttavia, il codice del modulo Python sembrava essere derivato dalla sorgente a ps
, which I found here. ps
può in qualche modo ottenere il percorso eseguibile di ogni processo in esecuzione, ma i miei migliori sforzi per estrarre lo in modo che lo facesse non hanno avuto successo. C'è una funzione in print.c
chiamata getproclline
che sembra stia facendo la magia, ma quando eseguo lo stesso codice dal mio strumento da riga di comando, non riesco a recuperare l'eseguibile del processo per processi diversi dal mio.
Continuerò a sperimentare, ma senza prove più conclusive, sembra che la risposta di @ drawnonward sia la più corretta finora.
EDIT (molto tempo dopo)
Grazie alla risposta pointed to by Quinn Taylor, ho trovato qualcosa che funziona. Ottiene il percorso dell'eseguibile di ogni processo e quindi posso semplicemente prendere l'ultimo componente del percorso per ottenere il nome del processo effettivo.
#import <sys/proc_info.h>
#import <libproc.h>
int numberOfProcesses = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
pid_t pids[numberOfProcesses];
bzero(pids, sizeof(pids));
proc_listpids(PROC_ALL_PIDS, 0, pids, sizeof(pids));
for (int i = 0; i < numberOfProcesses; ++i) {
if (pids[i] == 0) { continue; }
char pathBuffer[PROC_PIDPATHINFO_MAXSIZE];
bzero(pathBuffer, PROC_PIDPATHINFO_MAXSIZE);
proc_pidpath(pids[i], pathBuffer, sizeof(pathBuffer));
if (strlen(pathBuffer) > 0) {
printf("path: %s\n", pathBuffer);
}
}
Mi sembra di ricordare una chiamata 'sysctl() che restituisce un elenco completo, sebbene i nomi dei processi siano stati troncati di una certa lunghezza. – Wevah
@Wevah è corretto. 'sysctl()' restituisce l'elenco completo, ma i nomi vengono troncati a 16 caratteri. Questo è l'articolo n. 2 nella lista. :) –
Ah, non ho visto 'sysctl()' menzionato (inoltre non ho fatto clic sul collegamento). (Anche votando la domanda, potrei usare queste informazioni!) – Wevah