En primer lugar, sé que se han formulado preguntas similares, pero las respuestas proporcionadas no han sido muy útiles (todas recomiendan una de las siguientes opciones).Recuperar nombres de procesos en ejecución
Tengo una aplicación de usuario que necesita determinar si un proceso en particular se está ejecutando. Esto es lo que sé sobre el proceso:
- El nombre
- El usuario (
root
) - Se debe estar ya en funcionamiento, ya que es un LaunchDaemon, lo que significa
- Su proceso padre debe haber
launchd
(pid 1)
He intentado varias formas de conseguir esto, pero ninguno ha funcionado hasta ahora. Esto es lo que he intentado:
Correr
ps
y analizando la salida. Esto funciona, pero es lento (fork
/exec
es caro), y me gustaría que sea lo más rápido posible.Utilizando la función
GetBSDProcessList
listed here. Esto también funciona, pero la forma en que dicen recuperar el nombre del proceso (accediendo alkp_proc.p_comm
de cada estructurakinfo_proc
) es defectuosa. Elchar*
resultante sólo contiene los primeros 16 caracteres del nombre del proceso, que se pueden ver en la definición de lakp_proc
estructura:#define MAXCOMLEN 16 //defined in param.h struct extern_proc { //defined in proc.h ...snip... char p_comm[MAXCOMLEN+1]; ...snip... };
Usando libProc.h para recuperar la información del proceso:
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); }
Estos trabajos , excepto que tiene el mismo defecto que
GetBSDProcessList
. Solo se devuelve la primera parte del nombre del proceso.Utilizando el ProcessManager function en carbono:
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); }
esto no funciona. Solo devuelve un proceso que está registrado con el WindowServer (o algo así). En otras palabras, solo devuelve aplicaciones con UI, y solo para el usuario actual.
No puedo usar
-[NSWorkspace launchedApplications]
, ya que debe ser compatible con 10.5. Además, esto solo devuelve información sobre las aplicaciones que aparecen en el Dock para el usuario actual.
que saben que es posible para recuperar el nombre de los procesos (desde ps
puede hacerlo) que se ejecuta, pero la pregunta es "¿Puedo hacerlo sin que se bifurcan y exec'ing ps
?".
¿Alguna sugerencia?
EDITAR
Después de hacer muchas más investigaciones, he sido incapaz de encontrar una manera de hacer esto. Encontré this SO question, que se refería a this C file in a python module. Esto fue realmente útil al tratar de usar los valores KERN_PROCARGS
en una llamada sysctl
.
Sin embargo, el código del módulo Python parecía derivarse de la fuente a ps
, which I found here. ps
de alguna manera puede obtener la ruta ejecutable de cada proceso en ejecución, pero mis mejores esfuerzos para extraer cómo ha sido infructuoso. Hay una función en print.c
llamada getproclline
que parece estar haciendo la magia, pero cuando ejecuto el mismo código desde mi propia herramienta de línea de comandos, no puedo recuperar el proceso ejecutable para ningún otro proceso que no sea el mío.
Seguiré experimentando, pero sin pruebas concluyentes, parece que la respuesta de @ drawnonward es la más correcta hasta ahora.
EDITAR (mucho tiempo después)
Gracias a la respuesta pointed to by Quinn Taylor, he encontrado algo que funciona. Obtiene la ruta ejecutable de cada proceso, y luego puedo tomar el último componente de ruta para obtener el nombre del proceso real.
#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);
}
}
Me parece recordar una llamada 'sysctl()' que devuelve una lista completa, aunque los nombres del proceso se truncaron en una cierta longitud. – Wevah
@Wevah eso es correcto. 'sysctl()' devuelve la lista completa, pero los nombres se truncan a 16 caracteres. Ese es el artículo # 2 en la lista. :) –
Ah, no vi 'sysctl()' mencionado (tampoco hice clic en el enlace). (¡Votando la pregunta también, como podría usar esta información!) – Wevah