Во-первых, я знаю, что схожие вопросы были заданы, но предоставленные ответы пока не очень помогли (все они рекомендуют один из следующих вариантов).
У меня есть пользовательское приложение, которое должно определить, работает ли какой-то конкретный процесс. Вот что я знаю о процессе:
- Имя
- Пользователь (
root
) - Он должен быть запущен, так как это LaunchDaemon, что означает
- Его родительский процесс должен быть
launchd
(pid 1)
Я пробовал несколько способов получить это, но до сих пор никто не работал. Вот что я пробовал:
-
Запуск
ps
и синтаксический анализ вывода. Это работает, но оно медленное (fork
/exec
дорого), и я хотел бы, чтобы это было как можно быстрее. -
Использование функции
GetBSDProcessList
приведенной здесь. Это также работает, но способ, которым они говорят, чтобы получить имя процесса (доступ кkp_proc.p_comm
из каждой структурыkinfo_proc
), является ошибочным. Результирующийchar*
содержит только первые 16 символов имени процесса, которые можно увидеть в определении структурыkp_proc
:#define MAXCOMLEN 16 //defined in param.h struct extern_proc { //defined in proc.h ...snip... char p_comm[MAXCOMLEN+1]; ...snip... };
-
Используя libProc.h, чтобы получить информацию о процессе:
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); }
Это работает, за исключением того, что имеет тот же недостаток, что и
GetBSDProcessList
. Возвращается только первая часть имени процесса. -
Используя Функция ProcessManager в Carbon:
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); }
Это не работает. Он возвращает процесс, зарегистрированный в WindowServer (или что-то в этом роде). Другими словами, он только возвращает приложения с пользовательскими интерфейсами и только для текущего пользователя.
-
Я не могу использовать
-[NSWorkspace launchedApplications]
, так как это должно быть совместимо с 10.5. Кроме того, это только возвращает информацию о приложениях, которые отображаются в Dock для текущего пользователя.
Я знаю, что можно получить имя запущенных процессов (так как ps
может это сделать), но вопрос: "Могу ли я сделать это без forking и exec'ing ps
?".
Любые предложения?
ИЗМЕНИТЬ
После проведения гораздо большего исследования я не смог найти способ сделать это. Я нашел этот вопрос SO, который ссылался на этот файл C в модуле python, Это было действительно полезно при попытке использовать значения KERN_PROCARGS
в вызове sysctl
.
Однако код модуля Python, по-видимому, был получен от источника до ps
, который я нашел здесь. ps
может каким-то образом получить исполняемый путь для каждого запущенного процесса, но мои лучшие усилия, чтобы выяснить, как это делается, не удалось. Там функция в print.c
называется getproclline
, которая, кажется, делает магию, но когда я запускаю тот же код из своего собственного инструмента командной строки, я не могу получить исполняемый файл процесса для любых процессов, отличных от моего собственного.
Я продолжу экспериментировать, но без каких-либо убедительных доказательств, похоже, что ответ @drawnonward является самым правильным до сих пор.
EDIT (спустя долгое время)
Благодаря ответу указанному Куинн Тейлор, я нашел что-то, что работает. Он получает исполняемый путь каждого процесса, а затем я могу просто захватить последний компонент пути, чтобы получить фактическое имя процесса.
#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);
}
}