1. Dashboard
  2. Forum
    1. Unerledigte Themen
  3. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team-Mitglieder
    4. Trophäen
    5. Mitgliedersuche
  4. Tutorial Bereich
  • Anmelden
  • Registrieren
  • Suche
Dieses Thema
  • Alles
  • Dieses Thema
  • Dieses Forum
  • Seiten
  • Forum
  • Lexikon
  • Erweiterte Suche
  1. Informatik Forum
  2. Webmaster & Internet
  3. Entwicklung

temporaeres schlieszen von stdin/stdout

  • Kampi
  • 28. Juni 2008 um 19:22
  • Unerledigt
  • Kampi
    27
    Kampi
    Mitglied
    Reaktionen
    193
    Punkte
    7.828
    Beiträge
    1.468
    • 28. Juni 2008 um 19:22
    • #1

    ich habe ein programm das sich per commandline-switch auch in einem daemon modus betreiben laeszt. die daemonize() funktion ist nicht sonderlich spannend, im prinzip ein fork() in dem sich der parent prozess verabschiedet und das child weiter laeuft. zusaetzlich noch ein paar signal-handler, chdir, umask usw. wie ich in einem beispielcode gesehen habe werden fuer den daemon auch alle file deskriptoren geschlossen, was mir recht sinnvoll erscheint. wenn schon daemon, dann gscheit. die anzahl der maximalen deskriptoren hole ich mir per sysconf() und mach dann auf jeden einzelnen ein close(). soweit so gut. nur brauche ich zu einem spaeteren zeitpunkt wieder funktionierende 'stdin' und 'stdout', da ich den output von einem anderen prozess lesen will. auch hier wieder die klassiker aus sysprog (pipe, fork, dup2, close, exec). nur wie komme ich zu diesem zeitpunkt wieder an funktionierende 'stdin' und 'stdout'?

    prinzipiell gibt es 2 moeglichkeiten die mir eingefallen sind:
    *) ich mach alle deskriptoren bis auf stdin/out zu.
    *) ich sichere mir die 2 deskriptoren, schliesze alle bis auf die beiden und mache dann ein freopen.

    beides, vor allem ersteres, moeglichkeiten die funktionieren und fuer meine zwecke absolut ausreichend sind, aber kann es sein, dass man nach dem schlieszen _aller_ deskriptoren keine moeglichkeit mehr hat wieder an neue stdin/outs zu kommen? da weisz doch sicher jemand eine schoene moeglichkeit. aja, das ganze soll ausschlieszlich unter gnu/linux laufen, also portabilitaet ist nicht so wichtig. und ein freopen("/dev/stdout,"w",stdout) funktioniert nicht.

    mfg. kampi

    Willfähriges Mitglied des Fefe-Zeitbinder-Botnets und der Open Source Tea Party.

    Einmal editiert, zuletzt von Kampi (28. Juni 2008 um 19:29)

  • michi204
    26
    michi204
    Mitglied
    Reaktionen
    63
    Punkte
    7.268
    Beiträge
    1.318
    • 29. Juni 2008 um 00:24
    • #2

    ich fürchte, auch mit guten heuristiken würde es die von dir gesuchte magische get_stdout()-funktion nicht schaffen zu eruieren, was du denn gerne als neuen stdout hättest (den alten gibts ja dann nicht mehr).

    schau dir mal

    Code
    ls -l /dev/stdout

    an, das erklärt, warum freopen() nicht geht.

    und wie liest du dann von deinem dämon aus über stdin/out von einem anderen prozess daten ein? bzw. wozu brauchst du da stdin/stdout, du kannst ja einfach so ein(e) datei/pipe/socket öffnen. oder anders gefragt, was ist denn bei dir stdin und stdout für den dämon?

    lg,
    michi

  • Kampi
    27
    Kampi
    Mitglied
    Reaktionen
    193
    Punkte
    7.828
    Beiträge
    1.468
    • 29. Juni 2008 um 18:29
    • #3

    erstmal danke fuer die antwort.

    Zitat von michi204

    ich fürchte, auch mit guten heuristiken würde es die von dir gesuchte magische get_stdout()-funktion nicht schaffen zu eruieren, was du denn gerne als neuen stdout hättest (den alten gibts ja dann nicht mehr).

    sehe ich genau so. es wuerde mich wundern wenn es die magie gaebe, aber ich habe gehofft es kennt vlt. jemand einen C-trick, der mir noch nicht unter gekommen ist.

    Zitat von michi204

    i
    schau dir mal

    Code
    ls -l /dev/stdout

    an, das erklärt, warum freopen() nicht geht.

    jop, hab ich gemacht und es ist mir auch vollkommen klar warum es so nicht funktioniert. das einzige was geht ist ein backup machen, dann bis aufs backup closen, mir "/dev/fd/$BACKUP" zusammenbaun und ein freopen machen. aber das waer ja unlustig, ich will ja alle schlieszen, auch das backup :winking_face:

    Zitat von michi204


    und wie liest du dann von deinem dämon aus über stdin/out von einem anderen prozess daten ein? bzw. wozu brauchst du da stdin/stdout, du kannst ja einfach so ein(e) datei/pipe/socket öffnen. oder anders gefragt, was ist denn bei dir stdin und stdout für den dämon?

    ich denke das funktioniert nicht so einfach. bitte korrigiert mich wenn ich in sysprog nicht gut aufgepasst habe, aber ich lege die pipe an, forke meinen daemon und rufe dann im parent ein exec auf. ueber das aufgerufene parent programm habe ich nicht wirklich kontrolle, dem kann ich auch nicht sagen dass es auf pfd (den ich durch pipe() erzeugt habe) schreiben soll. dieses programm schreibt einfach auf "seinen" stdout. den hab ich aber vorher geschlossen (weit vor dem fork).

    ich zeigs dir anhand folgendem test-code.
    dummy.c: ueber das programm habe ich keine keine kontrolle, das ist einfach so vorhanden:

    Code
    #include <stdio.h>
    
    
    int main(int argc, char **argv)
    {
        printf("%s spricht\n", argv[0]);
    
    
        return 0;
    }

    daemon.c: so ist ca mein daemon aufgebaut. das daemonize() wird einfach durch das schlieszen der deskriptoren 0-9 simuliert:

    C
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <strings.h>
    
    
    #define SIZE 1024
    
    
    int main(int argc, char **argv)
    {
        int pfd[2];
        int pid,i;
        int nread;
        char buf[SIZE];
    
    
        /* SIMULATE daemonize() */
        /* for(i = 0; i < 10; i++) */
        /*    close(i); */
    
    
        if (pipe(pfd) == -1)
        {
            perror("pipe failed");
            exit(EXIT_FAILURE);
        }
    
    
        if ((pid = fork()) < 0)
        {
            perror("fork failed");
            exit(EXIT_FAILURE);
        }
        if (pid == 0) /* child */
        {
            close(pfd[1]);
            dup2(pfd[0], STDIN_FILENO);
            bzero(buf, SIZE);
            while ((nread = read(pfd[0], buf, SIZE)) != 0)
            {
                printf("got input:%s",buf);
            }
            exit(EXIT_SUCCESS);
        } 
        else /* parent */
        {
            close(pfd[0]);
            dup2(pfd[1], STDOUT_FILENO);
            close(pfd[1]);
            execlp("./dummy", "dummy",
                    (char *) 0);
            exit(EXIT_SUCCESS);
        }
        return EXIT_SUCCESS;
    }
    Alles anzeigen

    das funktioniert so auch ganz gut wenn man "daemon" startet, nur sobald man die die zwei zeilen fuer das simulierte daemonize auskommentiert spricht gar nix mehr.

    Willfähriges Mitglied des Fefe-Zeitbinder-Botnets und der Open Source Tea Party.

    3 Mal editiert, zuletzt von Kampi (29. Juni 2008 um 18:41)

  • michi204
    26
    michi204
    Mitglied
    Reaktionen
    63
    Punkte
    7.268
    Beiträge
    1.318
    • 29. Juni 2008 um 18:53
    • #4
    Zitat von Kampi

    ich denke das funktioniert nicht so einfach. bitte korrigiert mich wenn ich in sysprog nicht gut aufgepasst habe, aber ich lege die pipe an, forke meinen daemon und rufe dann im parent ein exec auf. ueber das aufgerufene parent programm habe ich nicht wirklich kontrolle, dem kann ich auch nicht sagen dass es auf pfd (den ich durch pipe() erzeugt habe) schreiben soll. dieses programm schreibt einfach auf "seinen" stdout. den hab ich aber vorher geschlossen (weit vor dem fork).

    wieso schließt du den schon vor dem fork()? das parent soll ihn ja weiter erwenden, es würde also reichen, die fds im kind zu schließen, oder habe ich da jetzt was übersehen? nur als warnung, ich schreib auch relativ selten c-programme, und noch seltener systemnahe. :)

    bei meinem letzten dämon hat mir übrigens dieser guide geholfen, gleich alles richtig zu machen:

    http://www.unixguide.net/unix/programming/1.7.shtml

    lg,
    michi

  • Kampi
    27
    Kampi
    Mitglied
    Reaktionen
    193
    Punkte
    7.828
    Beiträge
    1.468
    • 30. Juni 2008 um 10:46
    • #5
    Zitat von michi204

    wieso schließt du den schon vor dem fork()? das parent soll ihn ja weiter erwenden, es würde also reichen, die fds im kind zu schließen, oder habe ich da jetzt was übersehen?

    berechtigte frage, aber im wirklichen programm gehts imho nicht anders. in dem beispielcode schaut das ganze ziemlich ungeschickt aus, keine frage, aber im richtigen programm "muss" ich schon vorher die deskriptoren zu machen. ich parse am anfang die optionen/argumente mit getopt und sobald "--daemon" daher kommt forke ich das erste mal in den background (insgesamt sind es 3 forks die daherkommen). und erst viel viel spaeter kommt dann die geschichte mit dem lesen eines anderen programms. somit ist es keine option einfach mal zu warten bis ich etwas lesen mag und dann schlau zu forken und dann schlau zu schlieszen. zu dem zeitpunkt hat das programm schon lange als daemon zu laufen, da es zb auch ueber startup-skripte gestarte werden kann. aber wie gesagt, ich werde einfach in daemonize() die notwendigen deskriptoren aurecht erhalten und alles ist im lot.

    Willfähriges Mitglied des Fefe-Zeitbinder-Botnets und der Open Source Tea Party.

  • michi204
    26
    michi204
    Mitglied
    Reaktionen
    63
    Punkte
    7.268
    Beiträge
    1.318
    • 1. Juli 2008 um 02:54
    • #6
    Zitat von Kampi

    berechtigte frage, aber im wirklichen programm gehts imho nicht anders. in dem beispielcode schaut das ganze ziemlich ungeschickt aus, keine frage, aber im richtigen programm "muss" ich schon vorher die deskriptoren zu machen. ich parse am anfang die optionen/argumente mit getopt und sobald "--daemon" daher kommt forke ich das erste mal in den background (insgesamt sind es 3 forks die daherkommen). und erst viel viel spaeter kommt dann die geschichte mit dem lesen eines anderen programms. somit ist es keine option einfach mal zu warten bis ich etwas lesen mag und dann schlau zu forken und dann schlau zu schlieszen. zu dem zeitpunkt hat das programm schon lange als daemon zu laufen, da es zb auch ueber startup-skripte gestarte werden kann. aber wie gesagt, ich werde einfach in daemonize() die notwendigen deskriptoren aurecht erhalten und alles ist im lot.

    jetzt versteh ich es erst ganz :)

    an diesem zeitpunkt würde ich den holzhammer gegen die person einsetzen, die mir derart unschöne vorgaben gemacht hat :winking_face:

    lg,
    michi

  • Maximilian Rupp 27. Dezember 2024 um 12:04

    Hat das Thema aus dem Forum Programmieren nach Entwicklung verschoben.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!

Benutzerkonto erstellen Anmelden

Benutzer online in diesem Thema

  • 1 Besucher

Rechtliches

Impressum

Datenschutzerklärung