Во-первых, я знаю, что подобные вопросы задавались, но предоставленные ответы пока не очень помогли (все они рекомендуют один из следующих вариантов).
У меня есть пользовательское приложение, котороеНеобходимо определить, работает ли конкретный процесс.Вот что я знаю о процессе:
- Имя
- Пользователь (
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
может это сделать), но вопрос в том, "Могу ли я сделать это без разветвления и исполнения ps
?".
Есть предложения?
РЕДАКТИРОВАТЬ
Проведя гораздо больше исследований, я не смог найти способ сделать это.Я нашел этот вопрос SO , который ссылался на этот файл C в модуле Python .Это было действительно полезно при попытке использовать значения KERN_PROCARGS
в вызове sysctl
.
Однако код модуля Python, похоже, был получен из исходного кода ps
, , который я нашел здесь.ps
может каким-то образом получить путь к исполняемому файлу для каждого запущенного процесса, но мои лучшие усилия по извлечению того, как делает это, оказались безуспешными.В print.c
есть функция, называемая getproclline
, которая, кажется, творит чудеса, но когда я запускаю тот же код из моего собственного инструмента командной строки, я не могу получить исполняемый файл процесса для любых процессов, кроме моего.
Я буду продолжать экспериментировать, но без более убедительных доказательств, похоже, что ответ @ drawnonward является наиболее правильным на сегодняшний день.
РЕДАКТИРОВАТЬ (долгое время спустя)
Благодаря ответу , на который указал Куинн Тейлор , я нашел кое-что, что работает.Он получает путь к исполняемому файлу каждого процесса, а затем я могу просто взять последний компонент пути, чтобы получить фактическое имя процесса.
#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);
}
}