C : Prozesskommunikation

N

Nano

Foren As
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.
 
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...
 
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
 
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.
 
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.
 
Wenn ich das richtig verstanden habe erstellt fork nicht nur einen neuen prozess sondern "schaltet" zwischen diesen auch um, hier inizialisiert durch sleep();
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..

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.
Das kann nicht sein.

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
Wie meinst du das? Solange die shell keine Befehle bekommt, ist sie doch quasi in "standby".
 
schau mal auf www.pronix.de da sollte es ein openbook zur linux-unix programmierung geben in welchem dieses thema behandelt wird
 
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".

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;
}
 
Zuletzt bearbeitet:
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.
 
Zuletzt bearbeitet:
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 )
 
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
 

Ähnliche Themen

Unix Webserver mit HTML Seite erstellen

Prozesskommunikation mit PIPES - wie funktioniert das?

NagiosGrapher 1.7.1 funktioniert nicht

C HTTP request

Auf Child warten das nicht beendet wird ?

Zurück
Oben