Namen von laufenden Prozessen abrufen

Lesezeit: 6 Minuten

Benutzer-Avatar
David DeLong

Zunächst einmal weiß ich, dass ähnliche Fragen gestellt wurden, aber die Antworten waren bisher nicht sehr hilfreich (alle empfehlen eine der folgenden Optionen).

Ich habe eine Benutzeranwendung, die feststellen muss, ob ein bestimmter Prozess ausgeführt wird. Folgendes ist mir über den Ablauf bekannt:

  • Der Name
  • Der Nutzer (root)
  • Es sollte bereits ausgeführt, da es sich um einen LaunchDaemon handelt, was bedeutet
  • Sein übergeordneter Prozess sollte sein launchd (PID 1)

Ich habe mehrere Möglichkeiten ausprobiert, um dies zu erreichen, aber bisher hat keine funktioniert. Folgendes habe ich versucht:

  1. Betrieb ps und Analysieren der Ausgabe. Das funktioniert, ist aber langsam (fork/exec ist teuer), und ich möchte, dass dies so schnell wie möglich geht.

  2. Verwendung der GetBSDProcessList Funktion hier aufgeführt. Dies funktioniert auch, aber die Art und Weise, wie sie sagen, um den Prozessnamen abzurufen (Zugriff auf kp_proc.p_comm von jedem kinfo_proc Struktur) ist fehlerhaft. Das Ergebnis char* enthält nur die ersten 16 Zeichen des Prozessnamens, der in der Definition des zu sehen ist kp_proc Struktur:

    #define MAXCOMLEN 16 //defined in param.h
    struct extern_proc {  //defined in proc.h
      ...snip...
      char p_comm[MAXCOMLEN+1];
      ...snip...
    };
  3. Verwenden libProc.h So rufen Sie Prozessinformationen ab:

    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);
    }

    Das funktioniert, außer es hat den gleichen Fehler wie GetBSDProcessList. Nur der erste Teil des Prozessnamens wird zurückgegeben.

  4. Verwendung der ProcessManager-Funktion in Kohlenstoff:

    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);
    }

    Das funktioniert nicht. Es gibt nur Prozesse zurück, die beim WindowServer (oder so ähnlich) registriert sind. Mit anderen Worten, es werden nur Apps mit UIs und nur für den aktuellen Benutzer zurückgegeben.

  5. Ich kann nicht verwenden -[NSWorkspace launchedApplications], da diese 10.5-kompatibel sein muss. Außerdem werden nur Informationen zu Anwendungen zurückgegeben, die für den aktuellen Benutzer im Dock angezeigt werden.

Ich weiß, dass es ist möglich um den Namen laufender Prozesse abzurufen (seit ps kann es tun), aber die Frage ist “Kann ich es tun, ohne zu forken und auszuführen ps?”.

Irgendwelche Vorschläge?

BEARBEITEN

Nachdem ich viel mehr recherchiert habe, konnte ich keine Möglichkeit finden, dies zu tun. Ich habe diese SO-Frage gefunden, auf die verwiesen wurde diese C-Datei in einem Python-Modul. Dies war wirklich nützlich bei dem Versuch, die zu verwenden KERN_PROCARGS Werte in a sysctl Anruf.

Der Code des Python-Moduls schien jedoch von der Quelle abgeleitet zu sein ps, die ich hier gefunden habe. ps kann irgendwie den ausführbaren Pfad jedes laufenden Prozesses erhalten, aber ich bemühe mich nach besten Kräften, ihn zu extrahieren wie seine dabei waren erfolglos. Da ist eine Funktion drin print.c genannt getproclline Das scheint die Magie zu sein, aber wenn ich denselben Code in meinem eigenen Befehlszeilentool ausführe, kann ich die ausführbare Prozessdatei nicht für andere Prozesse als meine eigenen abrufen.

Ich werde weiter experimentieren, aber ohne schlüssigere Beweise sieht es so aus, als wäre die Antwort von @drawnonward bisher die richtigste.


EDIT (lange Zeit später)

Dank der Antwort, auf die Quinn Taylor hingewiesen hat, habe ich etwas gefunden, das funktioniert. Es erhält den ausführbaren Pfad jedes Prozesses, und dann kann ich einfach die letzte Pfadkomponente abrufen, um den tatsächlichen Prozessnamen zu erhalten.

#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);
    }
}

  • Ich erinnere mich an a sysctl() -Aufruf, der eine vollständige Liste zurückgibt, obwohl die Prozessnamen bei einer bestimmten Länge abgeschnitten wurden.

    – Wevah

    10. Juni 2010 um 22:06 Uhr


  • @Wevah das ist richtig. sysctl() gibt die vollständige Liste zurück, aber die Namen werden auf 16 Zeichen gekürzt. Das ist Punkt 2 in der Liste. 🙂

    – David DeLong

    10. Juni 2010 um 22:58 Uhr

  • Ah, ich habe nicht gesehen sysctl() erwähnt (ich habe den Link auch nicht angeklickt). (Ich stimme auch für die Frage ab, da ich diese Informationen verwenden könnte!)

    – Wevah

    10. Juni 2010 um 23:01 Uhr


  • @DaveDeLong Ich habe eine Anwendung, bei der NSUIElement auf 1 gesetzt ist. Ich erhalte den Anwendungsnamen mit der ProcessManager-Funktion.

    – Parag Bafna

    2. März 2012 um 11:14 Uhr


  • @DaveDeLong Ich verwende Ihre Lösung (letzte Pfadkomponente des ausführbaren Pfads), fühle mich aber unwohl. Wieso den? weil im MacOS-X-Aktivitätsmonitor “Prozessname” häufig anders ist als der Name der ausführbaren Binärdatei, von der aus der Prozess gestartet wurde. Ich frage mich, WAS IST der Prozessname.

    – Motti Schoner

    19. Oktober 2020 um 16:23 Uhr

Benutzer-Avatar
Quinn Taylor

Was ist mit dieser Antwort auf eine verwandte Frage? https://stackoverflow.com/a/12274588/120292 Dies gibt vor, den vollständigen Pfad für einen Prozess durch die PID zu erhalten, und Sie können nur die letzte Pfadkomponente abrufen.

Benutzer-Avatar
nach vorne gezogen

Die einzige vollständige Liste der laufenden Prozesse wird von 2 oben bereitgestellt und fragt den Kernel. Den tatsächlichen Namen des Prozesses zu erhalten, ist nicht einfach. Kurz gesagt, Sie suchen die PID in jeder anderen Quelle, die Sie finden können, bis Sie eine Übereinstimmung finden.

Für einige Prozesse funktioniert Folgendes:

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

Bei einigen Prozessen können Sie die PID in den Ergebnissen von nachschlagen [[NSWorkspace sharedWorkspace] launchedApplications] durch NSApplicationProcessIdentifier. Verfügbar mit 10.2 und höher. Die meisten, aber vielleicht nicht alle Elemente in dieser Liste sind die gleichen wie CopyProcessName oben.

Bei einigen Prozessen können Sie die Prozessargumente nachschlagen und den vollständigen Pfad aus dem ersten Argument erhalten. Ähnlich wie beim Abrufen der ursprünglichen Liste, aber mit KERN_PROCARGS oder KERN_PROCARGS2 als zweitem MIB-Wert. Das ist was ps macht gerade.

Bei einigen Prozessen bleiben Sie beim 16-stelligen p_comm hängen.

  • +1 das sieht recht vielversprechend aus! Das bekommen ProcessSerialNumber hat nicht funktioniert, aber ich werde es versuchen KERN_PROCARGS herangehen und berichten.

    – David DeLong

    10. Juni 2010 um 21:06 Uhr

  • KERN_PROCARGS und KERN_PROCARGS2 funktionieren, wenn meine App auch so läuft root. Leider ist es nicht. 🙁

    – David DeLong

    10. Juni 2010 um 21:51 Uhr

  • Ja, ps ist setuid root. Ich denke, es gibt eine spezielle Gruppe, vielleicht procmod, die auch auf diese zugreifen kann. Früher gab es eine ganze undokumentierte CPS-Suite für dieses Zeug, aber es scheint veraltet zu sein. Sieht so aus, als hätte Apple dies zu einem Sicherheitsproblem gemacht.

    – nach vorne gezogen

    15. Juni 2010 um 3:28 Uhr

Ich bin mir nicht sicher, ob es das ist, wonach Sie suchen, aber könnten Sie das verwenden? LaunchServices API mit __LSCopyApplicationArrayInFrontToBackOrder? Ich habe davon gehört, aber nie selbst benutzt. Nachdem Sie etwas gegoogelt haben, finden Sie hier ein Codebeispiel, das möglicherweise das liefert, wonach Sie suchen. Ich weiß es wirklich nicht und vermute ein wenig 😉

http://gist.github.com/163918

Bearbeiten

Eigentlich Ha. Hier ist ein Stack Overflow-Beitrag, der dies als Antwort und Links zu demselben Beitrag gibt, auf den ich verlinkt habe …

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

  • OP möchte den Namen eines Nicht-Anwendungsprozesses (ein Unix-Start-Daemon, der als Root ausgeführt wird, ohne Benutzeroberfläche und ohne Windows-Server-Registrierung), also ist diese Antwort – obwohl sehr interessant, nicht für diese Frage …

    – Motti Schoner

    19. Oktober 2020 um 16:32 Uhr

1384190cookie-checkNamen von laufenden Prozessen abrufen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy