Article View: de.comp.lang.c++
Article #177Re: Prg starten und kontrollieren
From: Joerg Koenig
Date: Mon, 31 Jul 1995 09:26
Date: Mon, 31 Jul 1995 09:26
115 lines
4667 bytes
4667 bytes
In article <3vdt67$rhl@news.uni-paderborn.de>, ulliull@uni-paderborn.de (Christian Ullenboom ) says:
>
>Hallo,
>
>ich m"ochte ein grafgisches Front-End f"ur ispell
>programmieren. (Nur UNIX) Dazu soll ispell aus einem Programm auusgerufen
>werden, die Tastaturdr"cuke dann an das Prg. weitergeleitet
>werden. Es w"are ja ganz sch"on wenn man das mit Streams
>machen kann.
>
>Mit system() kann ich zwar das Prg starten, aber wie steuere ich
>den Ablauf, Ideen??
>
> Ulli
>
system() ist gedacht, um mal schnell ein Programm zu starten und auf
dessen Beendigung zu warten. Fuer Prozessteuerung also gaenzlich
ungeeignet.
Fuer solche Aufgaben ist es wesentlich sinnvoller mittels der
Systemfunktionen fork(2), exec(2), pipe(2) und poll(2)/select(3C) zu arbeiten.
Falls Du sehr geringe Anforderungen an eine solche Prozesssteuerung stellst
genuegt evtl. auch schon ein popen().
Hier mal ein Beispiel, wie Du mittels fork() und Co. eine Prozesskontrolle
aufbauen kannst (ich gehe einfach mal davon aus, dass Du poll(2) hast.
Ansonsten musst Du das ganze an select(3C) anpassen)
Ich mache es hier deshalb so ausfuehrlich, weil ich auf Grund Deines
Postings annehme, dass Du keinerlei Erfahrung auf diesem Gebiet hast,
und ich aus eigener Erfahrung weiss, dass Prozessteuerung kein so
ganz simples Problem ist:
#include <stropts.h>
#include <poll.h>
...
int pipe0[2], pipe1[2], pipe2[2] ;
// pipe0 stellt die Verbindung zu stdin des neuen Prozesses her
// pipe1 zu stdout und pipe2 zu stderr...
if( pipe( pipe0 )!=0 || pipe( pipe1 )!=0 || pipe( pipe2 )!=0 )
// error-handling
int PID = fork() ;
if( PID == 0 ) {
// sohn-prozess: stdin, stdout und stderr zur pipe umbiegen...
dup2( pipe0[0], 0 ); close( pipe0[0] ) ; close( pipe0[1] ) ;
dup2( pipe1[1], 1 ); close( pipe1[0] ) ; close( pipe1[1] ) ;
dup2( pipe2[1], 2 ); close( pipe2[0] ) ; close( pipe2[1] ) ;
// Ein- und Ausgabe sollte ungepuffert sein, wenn das zu
// startende Programm interagiert (warum? siehe weiter unten).
// Ansonsten wuerde es genuegen, popen() zu verwenden, um die
// Prozesskontrolle hinreichend zu gewaehrleisten...
setbuf( stdin , NULL ) ;
setbuf( stdout, NULL ) ;
// eines von ..zig hundert exec's auswaehlen ...
execl( "/bin/sh", "-c", Command, NULL ) ;
perror( "execl" ) ;
exit( 1 ) ;
} else if( PID == -1 )
// error - handling
// hier geht jetzt der Papi weiter ...
FILE * Cmd_stdin = fdopen( pipe0[1], "w" ) ,
* Cmd_stdout = fdopen( pipe1[0], "r" ) ,
* Cmd_stderr = fdopen( pipe2[0], "r" ) ;
// Pipes zum Kommando sollten nicht puffern. Ansonsten kann es auf
// verschiedenen UNIX-System zu Verklemmungen kommen. Typisches
// Beispiel: Die Ausgabe des Programmes ist kurz und wird deshalb
// vom System gepuffert. Danach verlangt es eine Eingabe. Der steuernde
// Prozess wartet aber auf die Ausgabe (die gepuffert ist), bevor er
// erkennen kann, dass eine Eingabe erwartet wird...
setbuf( Cmd_stdin , NULL ) ;
setbuf( Cmd_stdout, NULL ) ;
setbuf( Cmd_stderr, NULL ) ;
struct pollfd port[ 3] ;
port[0].fd = 0 ; // die eigene Eingabe beruecksichtigen
port[0].events = POLLRDNORM | POLLRDBAND ; // diese Events sollten fuer
// die allermeisten Anwendungen
// korrekt sein.
port[1].fd = fileno( Cmd_stdout ) ;
port[1].events = POLLRDNORM | POLLRDBAND ;
port[2].fd = fileno( Cmd_stderr ) ;
port[2].events = POLLRDNORM | POLLRDBAND ;
poll( port, 3, -1 ) ; // siehe man-page fuer Parameter 3 ...
// Nun die Kanaele pruefen, was angekommen ist ...
if( port[0].revents & (POLLRDNORM | POLLRDBAND) )
// Eingabe von der Tastatur gekommen
// evtl. an Cmd_stdin weiterleiten ...
else if( port[1].revents & (POLLRDNORM | POLLRDBAND) )
// Ausgabe des Kommandos einlesen und verarbeiten
else if( port[2].revents & (POLLRDNORM | POLLRDBAND) )
// Programm's Fehlerausgabe einlesen und verarbeiten
else
// Falls Parameter 3 nicht auf -1 steht, kann hier eine
// Art Idle-Prozedur eingehangen werden. Auf jeden Fall
// sollte der Rueckgabewert von poll() auf Fehler
// geprueft werden (der Einfachheit halber weggelassen).
...
Mit Hilfe dieses Fragmentes sollte es moeglich sein eine geeignete
Prozessteuerung aufzubauen.
Tschuess
Joerg
Technical Details
Message-ID:
<3vi7ke$bj@mail.adg.de>Path:
arc1-ca.pugleaf.net!mail.adg.de!usenetReferences:
<3vdt67$rhl@news.uni-paderborn.de>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!mail.adg.de!usenet From: Joerg.Koenig@adg.de (Joerg Koenig) Newsgroups: de.comp.lang.c++ Subject: Re: Prg starten und kontrollieren Date: 31 Jul 1995 09:26:38 GMT Organization: Apotheken Dienstleistungs Gesellschaft mbH Message-ID: <3vi7ke$bj@mail.adg.de> References: <3vdt67$rhl@news.uni-paderborn.de> NNTP-Posting-Host: rincewind.adg.de X-Newsreader: WinVN 0.92.6+