Программно проверить, запущен ли процесс на Mac

Существует ли API-интерфейс Carbon/ Cocoa/C на Mac, который я могу использовать для перечисления процессов? Я ищу что-то вроде EnumProcesses в Windows.

Моя цель - проверить из кода, выполняется ли процесс (по имени).

Спасибо!

Ответ 1

TechZen говорит: Диспетчер процессов с декабря 2013 года полностью устарел.

А, я просто нашел Ссылка на Process Manager

Похож на GetNextProcess и GetProcessInfo помощь в определении того, что работает. Как предложил Дейв, GetBSDProcessList можно использовать, если вы ищете демонов, а не только процессов Carbon/Cocoa.

Ответ 2

Вот некоторые конкретные реализации и детали, обратите внимание, что proc- > kp_proc.p_comm имеет ограничение длины символов, поэтому я внедряю infoForPID: вместо этого

Cocoa:

[NSWorkspace launchApplications] (10.2+, устаревший в 10.7, очень ограниченный список процессов) [NSWorkspace runningApplications] (10.6+, менее ограниченный список процессов, но все еще не включает процессы демона)

Углерод:

- (NSArray*)getCarbonProcessList
{
    NSMutableArray *ret = [NSMutableArray arrayWithCapacity:1];
    ProcessSerialNumber psn = { kNoProcess, kNoProcess };
    while (GetNextProcess(&psn) == noErr) {
        CFDictionaryRef cfDict = ProcessInformationCopyDictionary(&psn,  kProcessDictionaryIncludeAllInformationMask);
        if (cfDict) {
            NSDictionary *dict = (NSDictionary *)cfDict;
            [ret addObject:[NSDictionary dictionaryWithObjectsAndKeys:
                            [NSString stringWithFormat:@"%@",[dict objectForKey:(id)kCFBundleNameKey]],@"pname",
                            [NSString stringWithFormat:@"%@",[dict objectForKey:@"pid"]],@"pid",
                            [NSString stringWithFormat:@"%d",(uid_t)getuid()],@"uid",                                               
                            nil]]; 
            CFRelease(cfDict);          
        }
    }
    return ret;
}

C: (см. Техническое Q & A QA1123 Получение списка всех процессов в Mac OS X)

- (NSArray*)getBSDProcessList
{
    NSMutableArray *ret = [NSMutableArray arrayWithCapacity:1];
    kinfo_proc *mylist;
    size_t mycount = 0;
    mylist = (kinfo_proc *)malloc(sizeof(kinfo_proc));
    GetBSDProcessList(&mylist, &mycount);
    int k;
    for(k = 0; k < mycount; k++) {
        kinfo_proc *proc = NULL;
        proc = &mylist[k];
        NSString *fullName = [[self infoForPID:proc->kp_proc.p_pid] objectForKey:(id)kCFBundleNameKey];
        if (fullName == nil) fullName = [NSString stringWithFormat:@"%s",proc->kp_proc.p_comm];
        [ret addObject:[NSDictionary dictionaryWithObjectsAndKeys:
                        fullName,@"pname",
                        [NSString stringWithFormat:@"%d",proc->kp_proc.p_pid],@"pid",
                        [NSString stringWithFormat:@"%d",proc->kp_eproc.e_ucred.cr_uid],@"uid",                                               
                        nil]];                                            
    }
    free(mylist);  
    return ret;
}

- (NSDictionary *)infoForPID:(pid_t)pid 
{
    NSDictionary *ret = nil;
    ProcessSerialNumber psn = { kNoProcess, kNoProcess };
    if (GetProcessForPID(pid, &psn) == noErr) {
        CFDictionaryRef cfDict = ProcessInformationCopyDictionary(&psn,kProcessDictionaryIncludeAllInformationMask); 
        ret = [NSDictionary dictionaryWithDictionary:(NSDictionary *)cfDict];
        CFRelease(cfDict);
    }
    return ret;
}

Ответ 3

Есть несколько способов сделать это:

  • Если это приложение с графическим интерфейсом с иконкой Dock, используйте -[NSWorkspace launchedApplications].
  • Откроем другой процесс (например, ps или верхний или любой другой) с помощью NSTask, прочитайте результаты и выполните поиск самостоятельно (или пропустите его через grep или что-то еще).
  • Используйте функцию GetBSDProcessList, описанную здесь: http://developer.apple.com/legacy/mac/library/#qa/qa2001/qa1123.html (я успешно использовал это в прошлом)

Ответ 4

В обзоре NSRunningApplicationClass говорится:

NSRunningApplication - это класс для управления и предоставления информации для одного экземпляра приложения. Отслеживаются только пользовательские приложения; это не предоставляет информацию о каждом процессе в системе.

и

Чтобы получить доступ к списку всех запущенных приложений, используйте метод runningApplications в NSWorkspace.

Я бы посоветовал взглянуть на Темы программирования служб Workspace

Ответ 5

Поздно, но если вам действительно нужно надежное решение, которое может проверить, работает ли какой-либо процесс (включая процессы BSD), вы можете сделать следующее:


#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <sys/sysctl.h>
#include <sys/types.h>

int main(int argc, const char* argv[]) {

  pid_t pid = atoi(argv[2]);  

  // This MIB array will get passed to sysctl()
  // See man 3 sysctl for details
  int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };

  struct kinfo_proc result;
  size_t oldp_len = sizeof(result);

  // sysctl() refuses to fill the buffer if the PID does not exist,
  // so the only way to detect failure is to set all fields to 0 upfront
  memset(&result, 0, sizeof(struct kinfo_proc));

  if (sysctl(name, 4, &result, &oldp_len, NULL, 0) < 0) { 
    perror("sysctl");
    return 1;
  }

  // SZOMB means a zombie process, one that is still visible but is not running anymore
  if (result.kp_proc.p_pid > 0 && result.kp_proc.p_stat != SZOMB) {
    printf("Process is running.\n");
  } else {
    printf("Process is NOT running.\n");
  }

  return 0;

}

Обратите внимание, что приведенный выше код является модифицированной версией одной из моих личных библиотек и не проверен. Тем не менее, должно быть понятно, как используется API, и он успешно работает в macOS 10.14.5.