C : Prozesskommunikation

Dieses Thema im Forum "C/C++" wurde erstellt von Nano, 26.02.2009.

  1. Nano

    Nano Foren As

    Dabei seit:
    02.12.2006
    Beiträge:
    93
    Zustimmungen:
    0
    Hallo zusammen, ich habe foglendes Problem

    ich schreibe an einem c programm das einen kind prozess erzeugen soll
    ( das klappt soweit auch ) dieses kind möchte ich jetzt etwas ausführen lassen z.b eine sqlplus kommandozeile.
    Mit meinem eigentlichen programm ( also dem vater ) möchte ich nun befehle an das kind bzw das vom kind ausgeführte programm senden allerdings ist mir nicht klar wie dies realisierbar ist.

    kleines beispiel :

    Code:
    
    	 int new_process;
    
    	 new_process = fork();
    
    	  if (new_process<0)  fprintf(stderr, "error beim Aufruf von fork()\n");
    	
      // Ab hier wird unterschieden was welcher Prozess macht ?!
    
    	  if (new_process==0) {
    
    	    fprintf(stdout, "  Child: PID  : %d\n", getpid());
    	    fprintf(stdout, "  Child: PPID : %d\n", getppid());
    	    system("ls");
     
    	  }
    
    	  if (new_process>0)  {
    	    fprintf(stdout, "  Parent: PID : %d\n", getpid());
    	    fprintf(stdout, "  Parent: PPID: %d\n", getppid());
             }
    
    
    Was mir auch noch nicht ganz klar ist warum, beide meldungen ausgegeben werden ? Ich vermute das einmal das orignalprogramm mit 0 läuft und dann mittels fork das 2te mit > 0 gestartet wird ?

    Ich wäre für Anregungen und Tips dankbar.
     
  2. Anzeige

    Schau dir mal diese Kategorie an. Dort findest du bestimmt etwas.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  3. #2 Gott_in_schwarz, 26.02.2009
    Gott_in_schwarz

    Gott_in_schwarz ar0

    Dabei seit:
    22.04.2007
    Beiträge:
    546
    Zustimmungen:
    0
    Ort:
    Niedersachsen
  4. Nano

    Nano Foren As

    Dabei seit:
    02.12.2006
    Beiträge:
    93
    Zustimmungen:
    0
    die ideen hatte ich selbstverständlich auch, allerdings blicke ich bei den ansätzen mit pipes und fifos nicht wircklich durch weshalb ich mir hier etwas hilfe erhofft habe...
     
  5. espo

    espo On the dark side

    Dabei seit:
    17.05.2003
    Beiträge:
    391
    Zustimmungen:
    0
    Ort:
    Stuttgart
    Naja ein Sohn erstellst du mit fork( );. Das Ergebniss gibts du über exit( ... ) zurück, und das kannst du dann im "Vater" per wait( ) und WEXITSTATUS( ... ) abfragen.

    Ich würde das so machen das ergebnis aus dem SQL zeug in ne char array schreiben und dann exit(1) fuer Erfolg im Sohn exit(0) für Fehler und dann halt im Vater gucken was du zurück kriegst und dann halt weiter machen.
    Is nur so ein kurzer Gedanken abriss hab das vor ewigkeiten mal gemacht.

    Greetings
     
  6. #5 Gott_in_schwarz, 26.02.2009
    Gott_in_schwarz

    Gott_in_schwarz ar0

    Dabei seit:
    22.04.2007
    Beiträge:
    546
    Zustimmungen:
    0
    Ort:
    Niedersachsen
    Was verstehst du denn konkret nicht bei pipes? Das sind einfach filedescriptors, durch die du kommunizieren kannst wie durch jeden anderen filedescriptor auch.

    This yields that, which in turn yields this other that.
    Mit funktionierendem fork/pipe Beispiel.
    Have fun.
     
  7. Nano

    Nano Foren As

    Dabei seit:
    02.12.2006
    Beiträge:
    93
    Zustimmungen:
    0
    Also ich hab mich bemüht das ganze etwas besser zu verstehen und auch ein kleines beispiel geschrieben in dem die prozess kommunizieren

    Code:
    
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    
    int main (){
       int pid, j, i;
       int pfds[2];
       pipe(pfds);
       char buf[30];
    
       pid = fork();
    
    
    
       if (pid == 0)
       {
    
    
          /* Kindprozess
           * wenn fork eine 0 zurückgibt, befinden wir uns im Kindprozess
           */
          for (j=0; j < 10; j++)
          {
        	  printf ("Kindprozess:  %d (PID: %d)\n", j, getpid());
        	  write(pfds[1], "test", 5);
            sleep (1);
          }
          exit (0);
       }
       else if (pid > 0)
       {
          /* Vaterprozess
           * Gibt fork einen Wert größer 0 zurück, so ist dies die PID des Kindprozesses
           */
          for (i=0; i < 10; i++)
          {
             printf ("Vaterprozess: %d (PID: %d)\n", i, getpid());
             read(pfds[0], buf, 5);
             printf("PARENT: read \"%s\"\n", buf);
    
             sleep (1);
          }
       }
       else
       {
          /* Wird ein negativer Wert zurückgegeben, ist ein Fehler aufgetreten */
          fprintf (stderr, "Error");
          exit (1);
       }
       return 0;
    }
    
    
    
    

    Funktioniert soweit auch , das Kind schreibt etwas auf die pipe und der Vaterprozess liest es und gibt es aus.

    Wenn ich das richtig verstanden habe erstellt fork nicht nur einen neuen prozess sondern "schaltet" zwischen diesen auch um, hier inizialisiert durch sleep();

    Was ich nicht verstehe ist wie ich jetzt realisieren kann das z.b im kindprozess eine shell ausgeführt wird, die eingaben des vaters verarbeitet
    getestet hab ich dies per system("sh") sowie einer variable die diese nur einmal erstellt

    Code:
    //im kind
    	   if( once == 0){
    			   once = 1;
    			   system("sh");
    	   }
    
    
    wenn ich das programm starte wird die shell auch ausgeführt, nur wird erst wieder zum vater geschaltet wenn ich die shell mit "exit" beende.

    Also mein konkretes problem ist wie schaffe ich es das die shell in standby geht bis sie vom vater einen befehl erhält diesen verarbeitet ( auch asynchron z.b kommando mit sleep ) und dann wieder auf die eingabe des vaters wartet, ein umschalten mit sleep ist hier ja nicht möglich.
     
  8. #7 Gott_in_schwarz, 27.02.2009
    Gott_in_schwarz

    Gott_in_schwarz ar0

    Dabei seit:
    22.04.2007
    Beiträge:
    546
    Zustimmungen:
    0
    Ort:
    Niedersachsen
    Das hast du leider nicht richtig verstanden. fork() ist ein system-call, der einen neuen Prozess erstellt. Das Umschalten zwischen Prozessen ist dem Kernel(-scheduler) vorbehalten; das ist ja schließlich eine der Hauptaufgaben des Kernels..
    Es gibt afaik auch keine Möglichkeit "critical sections" zu schreiben, in denen der Prozess nicht unterbrochen werden darf. Nennt sich preemptive scheduling.

    Des Weiteren ist system("sh") sinnfrei, denn system führt das übergebene Kommando eh in einer shell aus
    Code:
    $ man 3 system
    SYSTEM(3)                                  Linux Programmer’s Manual                                 SYSTEM(3)
    
    NAME
           system - execute a shell command
    
    SYNOPSIS
           #include <stdlib.h>
    
           int system(const char *command);
    
    DESCRIPTION
           system()  executes  a command specified in command by calling /bin/sh -c command, and returns after the
           command has been completed.  During execution of the command, SIGCHLD will be blocked, and  SIGINT  and
           SIGQUIT will be ignored.
    Dein letztlich abgesetztes Kommando ist also "/bin/sh -c sh", was recht sinnlos erscheint..

    Warum schreibts du nicht einfach die Kommandos im Vaterprozess in die Pipe und lässt sie im Kindprozess mit system ausführen?
    Du kannst aber auch direkt stdin vom Kind (mit system("sh") am laufen) mit stdout vom Vater verbinden. Dazu gibt es auf der Seite auch ein Beispiel..

    Das kann nicht sein.

    Wie meinst du das? Solange die shell keine Befehle bekommt, ist sie doch quasi in "standby".
     
  9. #8 icephilipp, 28.02.2009
    icephilipp

    icephilipp Foren As

    Dabei seit:
    01.03.2008
    Beiträge:
    91
    Zustimmungen:
    0
    schau mal auf www.pronix.de da sollte es ein openbook zur linux-unix programmierung geben in welchem dieses thema behandelt wird
     
  10. #9 Nano, 28.02.2009
    Zuletzt bearbeitet: 28.02.2009
    Nano

    Nano Foren As

    Dabei seit:
    02.12.2006
    Beiträge:
    93
    Zustimmungen:
    0
    Also erstmal vielen dank für die viele Arbeit die du dir machst um mir das ganze etwas näher zu bringen.

    system("sh"); war nur ein beispiel es könnte auch system("sqlplus") oder etwas anderes kommandozeilen orientiertes sein.

    mein problem ist wenn ich im child system("sqlplus") starte ( von der command line aus ) wird die aktuelle shell zu sqlplus oder sh oder was auch immer ich mitgebe, eben das möchte ich nicht ich möchte weiter in der normalen commandline bleiben und über diese nachrichten an den im child ausgeführten prozess ( beispielsweise sqlplus ) weitergeben.

    also meinetwegen in der bash prompt mein programm starten und von dort sqlplus indirekt über das child ansprechen, sinn des ganzen ist es das ich so z.b eine kommandohistory erzeugen kann, den daten in und output verändern kann etc..
    wie ich diese veränderungen bewerkstellige weiss ich, wie ich allerdings den sql prozess anspreche ohne in der sql prompt zu sein allerdings nicht
    (sqlplus ist hier auch nur ein beispiel das wohl etwas mehr sinn macht als sh )



    hier das ganze als codebeispiel bis auf die stelle die ich nicht hinbekomme

    Code:
    
    
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    
    int main (){
       int pid;
       int pfds[2];
       pipe(pfds);
       char buf[30];
    
    
       pid = fork();
    
    
    
       if (pid > 0)
       {
    
             printf ("Vaterprozess: (PID: %d)\n", getpid());
             write(pfds[1], "test", 5);
    
    
             sleep(1);
    
       }else    if (pid == 0)
       {
    
    				 // starten von sqlplus
    
    
        	  printf ("Kindprozess:  (PID: %d)\n", getpid());
        	  read(pfds[0], buf, 5);
        	  printf("Kind: read \"%s\"\n", buf);
    
        	  // buf  ( gelesener befehl ) an sql geben und ausführen
        	  // rückgabe von sql an den parent schreiben
              // auf Daten von Parent warten und an sqlplus weiterleiten
       }
       else
       {
    
          fprintf (stderr, "Error");
          exit (1);
       }
       return 0;
    }
    
     
  11. #10 Gott_in_schwarz, 28.02.2009
    Zuletzt bearbeitet: 28.02.2009
    Gott_in_schwarz

    Gott_in_schwarz ar0

    Dabei seit:
    22.04.2007
    Beiträge:
    546
    Zustimmungen:
    0
    Ort:
    Niedersachsen
    Ich glaub nicht wirklich, dass ich dich verstehe. Hier mal ein kleines (quasi wörtlich abgeschriebenes) Beispiel aus dem Tutorial, das einer shell Kommandos zupipet.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    int main(void) {
        int pfds[2];
        pipe(pfds);
    
        if (!fork()) {
            close(1);       /* close normal stdout */
            dup(pfds[1]);   /* make stdout same as pfds[1] */
            close(pfds[0]); /* we don't need this */
    
            printf("echo hello cruel world\n");
            fflush(stdout);
            sleep(1);
    
            printf("echo 'scale=100;sqrt(2)'|bc -ql|perl -pe 's/\\\\\\n$//'\n");
            printf("exit\n");
        }
        else {
            close(0);       /* close normal stdin */
            dup(pfds[0]);   /* make stdin same as pfds[0] */
            close(pfds[1]); /* we don't need this */
    
            system("sh");
        }
        return 0;
    }
    Man beachte die severe backslash madness.

    Mal ne Frage am Rande: machst du das aus reinem Interesse, oder steht da ein praktisches Problem hinter?

    Zu mehr Hülfe bin ich grade nicht im Stande.
     
  12. Anzeige

    Vielleicht findest du HIER Antworten.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  13. Nano

    Nano Foren As

    Dabei seit:
    02.12.2006
    Beiträge:
    93
    Zustimmungen:
    0
    hm weiss nicht wie ich es noch besser umschrieben soll..


    wenn ich mit execl ... einen befehl ausführe erzeugt dieser eine shell führt den befehl aus und beendet sich, in der zwischenzeit ist mein vaterprozess allerdings blockiert.


    ich hätte gerne shell1 ( vater ) in der ich befehle eingeben kann die shell2 ( kind ) verarbeitet, auch befehle der form ls * | sleep 10 | grep "bla" und dabei soll shell1 nicht blockiert sein sondern weiter befehle an shell2 in form einer fifo oder an ein neues kind senden

    ein weiterer punkt wäre das diese 2te shell im kind nicht nach jedem befehl beendet wird wie es ja bei execl der fall ist sondern koninuierlich läuft und befehle abarbeitet.


    explizit :
    User hat eine shell vor sich und kann "beliebige" befehle eingeben
    diese werden im kindprozess abgearbeitet ( user kann weiterhin befehle eingeben => fifo oder weiteres child )
     
  14. Nano

    Nano Foren As

    Dabei seit:
    02.12.2006
    Beiträge:
    93
    Zustimmungen:
    0
    ich konnte das problem lösen,
    mittels execl im child und einem umbiegen der in und outkanäle
    vielen dank nochmal für die hilfe
     
Thema:

C : Prozesskommunikation

Die Seite wird geladen...

C : Prozesskommunikation - Ähnliche Themen

  1. Prozesskommunikation mit PIPES - wie funktioniert das?

    Prozesskommunikation mit PIPES - wie funktioniert das?: Hallo erstmal, Ich sitze gerade an einer C-Aufgabe und komme nicht so recht weiter. 3 Programme müssen geschrieben werden: 1. Eines, dass...