fremdes Programm starten und beenden
-
Hallo!
Ich möchte von meinem C-Programm aus ein fremdes Programm starten, aber nicht wie bei system() auf dessen beendigung warten, sonder direkt im Programm-Ablauf weitermachen und später irgendwann das fremde Programm beenden.
wie mach ich das?MfG
mastercpp
-
Das geht z. B. mit der Kombination aus fork() und execlp(). Mit fork() zunächst einen Kind-Prozess "abspalten" und in diesem mit execlp() das Programm starten, Beispiel:
if (fork() == 0) execlp("ls", "-l", "my_dir"); /* Kind-Prozess */ else /* Parent-Prozess */ { ... }
Mehr dazu (und andere Möglichkeiten) findest du in meinem Buch "C und Linux"
Martin
-
schau dir mal fork() und exec() bzw. dessen derivate an.
-
Martin G schrieb:
Das geht z. B. mit der Kombination aus fork() und execlp(). Mit fork() zunächst einen Kind-Prozess "abspalten" und in diesem mit execlp() das Programm starten, Beispiel:
if (fork() == 0) execlp("ls", "-l", "my_dir"); /* Kind-Prozess */ else /* Parent-Prozess */ { ... }
Mehr dazu (und andere Möglichkeiten) findest du in meinem Buch "C und Linux"
Martin
Das ist schonmal 'ne geniale Idee, aber leider passt sie nicht zu meinem Programm, denn dem fremden Programm muss ich einem bestimmten Parameter übergeben, den der Kind-Prozess dann nicht wisen kann:
#ifdef HAVE_CONFIG_H #include <config.h> #endif #include <iostream> #include <cstdlib> #include <string> #include <sys/types.h> #include <unistd.h> using namespace std; string strCh; string strZapdvb; string strSplit; string strFile; string strSystem; string strMplayer; int main(int argc, char *argv[]) { start: cout << "Channel (1-256; 0 to exit): "; cin >> strCh; // <- Hier frage ich den Parameter "Channel" ab. if (strCh == "0") goto end; strZapdvb = "zapdvb -o -n "; strSplit = " | split -b 2047m - "; strFile = "/windows/E/Temp.mpg"; strSystem = strZapdvb + strCh + strSplit + strFile; cout << "Executing: " << strSystem << endl; system(strSystem.c_str()); // <- Hier wird er übergeben an zapdvb. // Das TV-Programm wird auf die Festplatte // aufgezeichnet. // Wenn system() sofort nach dem Start // von zapdvb zurückkehren würde, könnte // ich mit mplayer die aufgezeichnete Datei // sehen, wärend weiter aufgezeichnet wird // (TimeShift) strMplayer = "mplayer "; strSystem = strMplayer + strFile + "*"; cout << "\nExecuting: " << strSystem << endl; system(strSystem.c_str()); goto start; end: return EXIT_SUCCESS; }
-
Wieso weiß der Kind-Prozess diesen Parameter nicht? Wenn du meinen Code an der Stelle einsetzt, wo du derzeit die Funktion system() aufrufst, müsste es doch gehen. Wenn der Kind-Prozess allerdings Daten/Informationen an den Parent-Prozess zurückschicken will, musst du Interprozesskommunikation (IPC) einsetzen (Pipes, FIFOs, Shared Mem, ...) oder die libpthread benutzen. Beides findest du in meinem Buch erklärt.
Martin
-
Ich habe mir auch schon die Frage nach einem Ersatz für die spawn-Funktions-Gruppe aus Winodws gestellt. Hab bis jetzt aber nichts gefunden.
@Martin G
Auch ich glaube nicht, dass das bei mastercpp's Beispiel funktioniert...
Wenn doch, zeig uns doch mal wie...
-
/usr/bin schrieb:
Auch ich glaube nicht, dass das bei mastercpp's Beispiel funktioniert...
Wenn doch, zeig uns doch mal wie...Ich denke, so:
if (fork() == 0) execlp(strZapdvb, strZapdvb, strCh, strSplit, strFile, NULL); else { sleep(60); /* 1 Minute Vorlauf schaffen */ strMplayer = "mplayer "; strSystem = strMplayer + strFile + "*"; cout << "\nExecuting: " << strSystem << endl; system(strSystem.c_str()); }
Martin
PS.: In einer Version der man-Page zu system() steht explizit, dass man stattdessen lieber fork() und exec..() verwenden sollte, und es ist auch der Code angegeben, wie system() damit ersetzt werden soll. Also, warum soll es nicht gehen???
-
Martin G schrieb:
if (fork() == 0) execlp(strZapdvb, strZapdvb, strCh, strSplit, strFile, NULL); else { sleep(60); /* 1 Minute Vorlauf schaffen */ strMplayer = "mplayer "; strSystem = strMplayer + strFile + "*"; cout << "\nExecuting: " << strSystem << endl; system(strSystem.c_str()); }
[...]
Also, warum soll es nicht gehen???
Hmmm... Wenn der Parent-Prozess in der Zeile "if (fork() == 0)" angelangt ist, wird der Child-Prozess gestartet, weil fork() != 0. Der Kind-Prozess fängt dann aber wieder vom Anfang der main()-Funktion an und fragt nach dem Channel... Oder habe ich fork() falsch verstanden?
@mastercpp:
Ist bei Zapdvb kein TimeShift-Programm dabei? Auf der Webseite steht das doch.
-
ne. der kind prozess startet hinter dem fork. der eltern prozess
bekommt als return wert von fork die pid des kindes und der kind
prozess als return wert 0:pid_t pid = fork(); // diese stelle wird von vater und kind erreicht // der vater hat eine pid > 0 // das kind die pid 0 switch ( pid ) { case -1: // fork ist fehlgeschlagen -> es wurde kein kindprozess erzeugt break; case 0: // hier startet der kind prozess break; default: // hier macht der vater prozess weiter break; }
-
/lib schrieb:
Hmmm... Wenn der Parent-Prozess in der Zeile "if (fork() == 0)" angelangt ist, wird der Child-Prozess gestartet, weil fork() != 0. Der Kind-Prozess fängt dann aber wieder vom Anfang der main()-Funktion an und fragt nach dem Channel... Oder habe ich fork() falsch verstanden?
Ja. Beide Prozesse befinden sich nach dem fork()-Aufruf in _genau_ dem gleichen Zustand, mit einer Ausnahme: Anhand der Rueckgabewert von fork() erkennt man, ob es der Vater oder der Sohn ist.