Получить имена запущенных процессов - PullRequest
28 голосов
/ 11 июня 2010

Во-первых, я знаю, что подобные вопросы задавались, но предоставленные ответы пока не очень помогли (все они рекомендуют один из следующих вариантов).

У меня есть пользовательское приложение, котороеНеобходимо определить, работает ли конкретный процесс.Вот что я знаю о процессе:

  • Имя
  • Пользователь (root)
  • Это должно уже работать,так как это LaunchDaemon, что означает
  • Его родительский процесс должен быть launchd (pid 1)

Я пробовал несколько способов получить это, но ни один до сих пор не работал,Вот что я попробовал:

  1. Запуск ps и анализ выходных данных.Это работает, но медленно (fork / exec дорого), и я бы хотел, чтобы это было как можно быстрее.

  2. Использование функции 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...
    };
  3. Использование 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.Возвращается только первая часть имени процесса.

  4. Использование функции 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 (или что-то в этом роде).Другими словами, он возвращает только приложения с пользовательским интерфейсом и только для текущего пользователя.

  5. Я не могу использовать -[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);
    }
}

Ответы [ 3 ]

8 голосов
/ 18 сентября 2012

А как насчет этого ответа на связанный вопрос? https://stackoverflow.com/a/12274588/120292 Это означает, что pid получает полный путь к процессу, и вы можете получить только последний компонент пути.

2 голосов
/ 11 июня 2010

Единственный полный список запущенных процессов представлен 2 выше, спрашивая ядро.Получить фактическое название процесса не так просто.В двух словах, вы ищите pid в любом другом источнике, который можете найти, пока не получите совпадение.

Для некоторых процессов будет работать следующее:

ProcessSerialNumber         psn;
CFStringRef             name = NULL;
status = GetProcessForPID( inPID , &psn );
if ( noErr == status ) CopyProcessName( &psn , &name );

Для некоторых процессов:Вы можете посмотреть pid по результатам [[NSWorkspace sharedWorkspace] launchedApplications] на NSApplicationProcessIdentifier.Доступный с 10.2 и позже.Большинство, но, возможно, не все элементы в этом списке будут такими же, как CopyProcessName выше.

Для некоторых процессов вы можете найти аргументы процесса и получить полный путь из первого аргумента.Аналогично получению исходного списка, но с использованием KERN_PROCARGS или KERN_PROCARGS2 в качестве второго значения MIB.Это то, что делает ps.

Для некоторых процессов вы застряли с 16 символами p_comm.

0 голосов
/ 11 июня 2010

Не уверен, что это то, что вы ищете, но не могли бы вы использовать LaunchServices API с __ LSCopyApplicationArrayInFrontToBackOrder? Я слышал об этом, но никогда не использовал это сам. После некоторого поиска, вот пример кода, который может предоставить то, что вы ищете? Я правда не знаю и немного догадываюсь;)

http://gist.github.com/163918

Редактировать

На самом деле, Ха. Вот пост переполнения стека, который дает это в качестве ответа и ссылки на тот же пост, на который я ссылался ...

http://www.stackoverflow.com/questions/945033/getting-the-list-of-running-applications-ordered-by-last-use

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...