System() und Rückgabe (PID) gesucht
-
Hallo zusammen,
ich möchte aus einem C++ Programm unter Linux (g++) ein Programm in der Kommandozeile aufrufen und mit & in den Hintergrund schieben.
In der Kommandozeile wird mir dann ja zb [1] 12342 zurückgegeben, wobei 12342 die PID ist, welche ich in C++ weiter verarbeiten möchte und benötige.Ich habe nur gerade eine Denksperre bzw. mir fehlt das Wissen dazu.
Mit system() scheint das nicht wirklich zu funktionieren.Gesucht ist quasi nur die Rückgabe der Kommandozeile beim Aufruf des Befehls.
Viele Grüße und schonmal Danke,
Kai
-
Die Funktion system() startet zunächst eine Shell und führt in dieser die angegebene Kommandozeile aus.
Wenn Du die Prozess-Nr. des auszuführenden Programms haben willst, solltest Du meines Erachtens besser mit fork() und execlp() arbeiten. fork() liefert Dir in diesem Fall ja die Nummer des neuen Prozesses.
-
Mhh fork() scheibt ja ne ganz große Nummer zu sein.
Aber ich blicke da net richtig durch.
fork() macht ja ne Kopie des aktuellen Prozesses und läuft an der gleichen Stelle weiter.Aber wie mache ich das, wenn ich eigentlich nen anderes Programm starten will also zb wget und dessen PID bekommen möchte?
Hast du / hat jemand da nen passendes Beispiel?
Viele Grüße,
Kai
-
Kai4711 schrieb:
Hast du / hat jemand da nen passendes Beispiel?
Voilà:
/* pipe2.c - Pipes als Standardein- und -ausgabe Beispielquelltext aus Gräfe:"C und Linux" */ # include <stdio.h> # include <unistd.h> # include <sys/wait.h> int main() { int fd1[2], fd2[2], l; char buffer[80]; if ((pipe(fd1) != 0) || (pipe(fd2) != 0)) { perror("pipe2: pipe() failed"); return(1); } if (fork() == 0) { close(fd1[1]); /* Kind-Prozess */ close(fd2[0]); if ((dup2(fd1[0], STDIN_FILENO) == -1) || (dup2(fd2[1], STDOUT_FILENO) == -1)) { perror("pipe2: dup2() failed"); return(1); } close(fd1[0]); close(fd2[1]); execlp("sort", "sort", NULL); perror("pipe2: execlp() failed"); return(1); } close(fd1[0]); /* Eltern-Prozess */ close(fd2[1]); write(fd1[1], "These\nlines\nshall\nbe\nsorted\n", 28); close(fd1[1]); wait(NULL); if ((l = read(fd2[0], buffer, 79)) == -1) perror("pipe2: read() failed"); else write(STDOUT_FILENO, buffer, l); close(fd2[0]); return(0); }
Wie Du siehst, ist fork() keine komplizierte Sache. Es wird halt ein Duplikat des aktuellen Prozesses erzeugt, der einzige Unterschied ist der Rückgabewert von fork() (Kind-Prozess: 0, Vater-Prozess: >0).
In dem obigen Beispiel werden zusätzlich die Standardein- und -ausgabe in Pipes umgelenkt, aber das ist für Dein Programm ja vielleicht nicht notwendig. Die Zeilen 15 bis 19 und 23 bis 31 könnten damit entfallen. (Natürlich nicht bei dem Beispiel mit "sort" als Kind-Prozess, weil sort dann keine Eingabe erhält.)PS.: Das Beispiel stammt aus meinem Buch "C und Linux".
-
cool danke!
Aber an welcher Stelle erhalte ich hier die PID von zB sort?
Hintergrund: Bei mir soll ein Prozess (wget) gestartet werden, und später irgendwann anhand seiner PID wieder gekillt werden.
Viele Grüße
Kai
-
Kai4711 schrieb:
cool danke!
Aber an welcher Stelle erhalte ich hier die PID von zB sort?
die Rückgabe von fork().
Wenn fork < 0 ==> Fehler
Wenn fork == 0 ==> Kindprozess. Kindprozess liest seine PID durch getpid() und die vom Vater mit getppid()
Wenn fork != 0 ==> Vaterprozess und die Rückgabe von fork entspricht der PID des Kindes. Du kannst dann kill(SIGKILL, rueckgabe_von_fork); aufrufen, wenn du das Kind killen willst.
-
Achso, und wenn ich im Kind eine Programm aufrufe (zB wget) hat es diese PID?
Ich dachte das Kind hätte eine PID und wenn ich irgendwas aufrufe hätte das dann auch wieder eine eigene PID?Grüße
Kai
-
Kai4711 schrieb:
Ich dachte das Kind hätte eine PID und wenn ich irgendwas aufrufe hätte das dann auch wieder eine eigene PID?
Für system() stimmt das -- für execlp() nicht! Die exec-Funktionen starten das Programm im gleichen Prozess (und kehren auch nicht wieder in das aufrufende C-Programm zurück).
-
Kai4711 schrieb:
Ich dachte das Kind hätte eine PID und wenn ich irgendwas aufrufe hätte das dann auch wieder eine eigene PID?
Das liegt aber am
system()
Funktionsaufruf. System macht einenfork()
und im Kindprozess wird execlp aufgerufen. Wie martinG erklärt hat, die exec-Familie ersetzt den Programmablauf vom dem Prozess durch den Code der neuen Binary. Eine mögliche Implmentierung von system wäre:int system(const char *command) { int status; pid_t child; child = fork(); if(child < 0) return -1; if(child == 0) { /* child proc. */ execlp("/bin/sh", "/bin/sh", "-c", command, NULL); _exit(1); /* keine Aufräumarbeit durch Kind, wenn exec versagt */ } waitpid(child, &status, 0); return WEXITSTATUS(status); }
-
supertux schrieb:
Das liegt aber am
system()
Funktionsaufruf. System macht einenfork()
und im Kindprozess wird execlp aufgerufen.Da muss ich Dich leider korrigieren:
system()
startet eine Shell (im Regelfall diebash
) und führt in dieser die Kommandozeile aus.
Anmerkung: Seit derbash2
wird von der Shell automatisch das S-Bit gelöscht, sodass ein Programm mit gesetztem S-Bit und Root-Rechten in dem mitsystem()
ausgeführten Programm keine Root-Rechte mehr hat.