Mehrere Prozesse + Überwachung. Ideenfindung



  • Hallo,

    ich habe Probleme mit dem Lösungsweg wie ich ein Problem bzgl. meiner Facharbeit lösen kann. Folgendes wird verlangt:
    ein eigenes Programm welches eine Konfigurationsdatei parsed in welcher Programme, Benutzer, Logverzeichniss, Parameter und Checkbefehl drin stehen. Im konkreten Fall geht es um DICOM-Empfänger.

    Die Datei habe ich bereits geparsed. Aber: ich müsste ja mehrere Threads erzeugen, um jedes Programm einzeln zu starten, UND noch ein "Prüfthread" welcher mit einem echo die Verfügbarkeit der Empfänger testet und ggf das Kind killt.

    Vorgestellt hatte ich es mir so:

    Mittels pthread_create in einer Schleife eine Funktion aufrufen, in welcher ich in einer while(1) schleife ein fork() mache. Der Kindprozess ist dann mein zu startendes Programm, der Vater wartet nur auf Kindestot zwecks Zombie. Ohne Threads funktioniert dies schon sehr gut. Kill ich das Kind, so wird sofort ein neues erzeugt, es bleibt kein Zombie zurück. Genau dies will ich nun automatisieren, dass ein weiterer Prozess prüft und ggf die PID killt und das mit mehreren "Kindern". In Kombination mit pthread_create() wird eben leider nicht jedes mal ein Kind erzeugt.

    Was ich jetzt schon per google finden konnte war, wie ein einzelner fork() erzeugt wird oder ein einzelner pthread_create(). Es wird weiterhin gewarnt pthread und fork() gleichzeitig zu verwenden. Daher nun meine bitte nach Ratschlägen, wie ich es mit fork() oder aber pthread handhaben könnte. Ich nehm jede Art von Tipps und Ratschlägen, gern auch Links zu Beispielen wo mehrere forks oder pthreads gleichzeitig existieren.

    Vllt stell ich mich auch bissl bedeppert an, da ich an sich kein Programmierer bin als FISI, aber Kleinbetrieb und es sei ja meine Ausbildung 🙄



  • Nebenan hätte ich jetzt vermutlich CreateProcess() und WaitForMultipleObjects() vorgeschlagen.
    Hier würde ich es so lösen: Der Vater-Prozess startet nacheinander per fork() alle nötigen Kinder und merkt sich deren pid's (z.B. in einer map<int,ProcessInfo>), dann ruft er wait() auf. Wenn das zurückkehrt, verrät es dir auch die pid des beendeten Prozesses, so daß du über die map<> herausfinden kannst, wie du ihn neu starten mußt.

    (ProcessInfo wäre hier eine selbstdefinierte Klasse, die alle Info aus deiner Konfiguration enthält)



  • Vielen Dank schonmal für den Tip. Im einfachsten Fall wäre dies doch so:

    int main (void)
    {
            pid_t pid1, pid2;
            int status;
    
            pid1 = fork();
            if (pid1 == 0)
                    execlp ("xcalc", NULL, NULL);
            pid2 = fork();
            if (pid2 == 0)
                    execlp ("xterm", NULL, NULL);
    
            if (WIFEXITED(status))
                    printf("exit\n");
            if (WIFSIGNALED(status))
                    printf("Killsig\n");
            if (WIFSTOPPED(status))
                    printf("Stopsig\n");
    
            return 0;
    }
    

    Compilen geht ohne Probleme, das Ausführen jedoch bringt mir:

    $ ./a.out
    exit
    (null): unknown options:

    Usage: (null) [-rpn] [-stipple]

    und öffnet nur das xterm

    Bei meinem funktionierenden Programm sieht es so aus:

    switch (pid = fork()) {
            case -1:
                    perror("konnte Kind nicht starten");
                    return EXIT_FAILURE;
            case 0:
                    kind_pid = getpid();
                    printf("Kind mit PID: %d\n", kind_pid);
                    execlp("xterm", NULL, NULL);
            default:
                    if (wait (&status) != pid){
                            perror("wait()");
                            return EXIT_FAILURE;
                    }
                    child_status (status);
            }
    

    Nur, da weiß ich nicht, ob der 2. fork() innerhalb dem switch oder ausserhalb kommen soll, daher oben die Lösung.



  • Was bringt es denn, den Inhalt von status auszuwertne, wenn du ihn nie gefüllt hast? (sprich: Wo ist der wait()-Aufruf?) Und die übrige Fehler-Auswertung ist auch nicht existent.
    Ansonsten ist es durchaus möglich, daß dein xcalc-Aufruf schiefgegangen ist - kannst du es denn alleinstehend ausführen?

    Und im fertigen Programm würde ich die einzelnen fork()-Aufrufe nacheinander ausführen (eventuell sogar in einer Schleife):

    for(int i=0;i<prozesse;++i)
    {
      pid_t child = fork();
      switch(child)
      {
      case -1:
        perror("Fehler bei fork");
        break;
      case 0:
        exec(prozess[i]);
        perror("Fehler bei exec");
        break;
      default:
        children[i] = child;//bzw in C++: children[child] = prozess[i];
      }
    }
    


  • Die Fehlerauswertung hab ich der Übersicht halber weggelassen gehabt. Nur die Signalauswertung drin, um zu verdeutlichen dass ich meine Zombis auch entsorge 😃

    Selbst mit deinem Vorschlag funktioniert das Programm so nicht mit mehreren Forks, auch in Schleife nicht. 😞

    int main (void)
    {
            int prozesse=2;
            int i;
            char *prozess[10];
    
            prozess[0] = malloc(sizeof(char) * 12);
            prozess[1] = malloc(sizeof(char) * 12);
            strcpy(prozess[0], "xcalc");
            strcpy(prozess[1], "xterm");
            pid_t children[10];
    
            for(i=0; i<prozesse;++i)
            {
                    pid_t child = fork();
                    switch(child)
                    {
                    case -1:
                            perror("Fehler bei fork");
                            break;
                    case 0:
                            execlp(prozess[i], NULL, NULL);
                            perror("Fehler bei exec");
                            break;
                    default:
                            children[i] = child;
                    }
            }
    
            return 0;
    }
    


  • Was kommen denn dort für Ergebnisse? Und hast du (nur zur Sicherheit) mal überprüft, ob der execlp("xcalc",NULL,NULL); Aufruf funktioniert, wenn du ihn alleine (ohne fork o.ä.) einsetzt?



  • Einzeln funktioniert der Aufruf:

    switch (pid = fork()) {
            case -1:
                    perror("konnte Kind nicht starten");
                    return EXIT_FAILURE;
            case 0:
                    kind_pid = getpid();
                    printf("Kind mit PID: %d\n", kind_pid);
                    execlp("xterm", NULL, NULL);
            default:
                    if (wait (&status) != pid){
                            perror("wait()");
                            return EXIT_FAILURE;
                    }
                    child_status (status);
    

    Egal, ob mit xcalc oder xterm - in beiden Fällen öffnet sich das Wunschprogramm.

    Fehlermeldung beim Starten ist jene:

    $ ./a.out
    (null): unknown options:

    Usage: (null) [-rpn] [-stipple]

    Tausch ich die Position von xcalc und xterm so öffnet sich der X-Rechner, und das Xterm bleibt zu 😕



  • Du solltest als Argument den Namen des Programms übergeben also so

    execlp("xterm","xterm",NULL);
    

    Ich weiß nicht ob es dein Problem löst, aber es ist mir aufgefallen



  • linux_c89 schrieb:

    Du solltest als Argument den Namen des Programms übergeben also so

    execlp("xterm","xterm",NULL);
    

    Ich weiß nicht ob es dein Problem löst, aber es ist mir aufgefallen

    Jawoll, nun startet auch xcalc. Vielen Dank euch 2 für die Hilfe!


Anmelden zum Antworten