Performance Problem: dier Code frisst 100% CPU Zeit...
-
Hi,
das ist erstma nur zum testen....
//User includes #include "main.h" //system includes #include <iostream> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/wait.h> #include <string.h> using namespace std; int App1_pid = 0; int App2_pid = 0; const char* App1path = "/home/user1/workspace/App1/App1"; const char* App2path = "/home/user1/workspace/App2/App2"; pipe_type App1_Pipe; pipe_type App2_Pipe; int run_executable( pipe_type &child_pipe, const char* progname, int &child_pid ) { if( pipe( child_pipe.pipe_stdin.pipe_fd ) == -1) { perror( "pipe" ); } //init stdin stream PIPE_READ_END( child_pipe.pipe_stdin.fnctl_flags ) = fcntl( PIPE_READ_END( child_pipe.pipe_stdin.pipe_fd ), F_GETFL ); fcntl( PIPE_READ_END( child_pipe.pipe_stdin.fnctl_flags ), F_SETFL, PIPE_READ_END( child_pipe.pipe_stdin.fnctl_flags ) | O_NONBLOCK ); if( pipe( child_pipe.pipe_stdout.pipe_fd ) == -1) { perror( "pipe" ); } //init stdout stream PIPE_READ_END( child_pipe.pipe_stdout.fnctl_flags ) = fcntl( PIPE_READ_END( child_pipe.pipe_stdout.pipe_fd ), F_GETFL ); fcntl( PIPE_READ_END( child_pipe.pipe_stdout.fnctl_flags ), F_SETFL, PIPE_READ_END( child_pipe.pipe_stdout.fnctl_flags ) | O_NONBLOCK ); if( pipe( child_pipe.pipe_stderr.pipe_fd ) == -1) { perror( "pipe" ); } //init stderr stream PIPE_READ_END( child_pipe.pipe_stderr.fnctl_flags ) = fcntl( PIPE_READ_END( child_pipe.pipe_stderr.pipe_fd ), F_GETFL ); fcntl( PIPE_READ_END( child_pipe.pipe_stderr.fnctl_flags ), F_SETFL, PIPE_READ_END( child_pipe.pipe_stderr.fnctl_flags ) | O_NONBLOCK ); int pid = vfork(); if( pid == -1 ) { perror("fork"); exit( EXIT_FAILURE ); } else if(pid == 0){ child_pid = getpid(); close( PIPE_WRITE_END( child_pipe.pipe_stdin.pipe_fd ) ); close( PIPE_READ_END( child_pipe.pipe_stdout.pipe_fd ) ); close( PIPE_READ_END( child_pipe.pipe_stderr.pipe_fd ) ); dup2( PIPE_READ_END( child_pipe.pipe_stdin.pipe_fd ), STDIN_FILENO ); dup2( PIPE_WRITE_END( child_pipe.pipe_stdout.pipe_fd ), STDOUT_FILENO ); dup2( PIPE_WRITE_END( child_pipe.pipe_stderr.pipe_fd ), STDERR_FILENO ); execl( progname, progname, (char*) 0 ); _exit(1); } else if( pid > 0 ){ close( PIPE_READ_END( child_pipe.pipe_stdin.pipe_fd ) ); close( PIPE_WRITE_END( child_pipe.pipe_stdout.pipe_fd ) ); close( PIPE_WRITE_END( child_pipe.pipe_stderr.pipe_fd ) ); } return 0; } int read_pipebuffer( char* buff, int &no_bytes, int pipe_fd ) { char tmpBuff[ MAX_BUFFER ] = {0}; int i; size_t bytesread = 0; fd_set fds; struct timeval tv; tv.tv_sec = tv.tv_usec = 0; FD_ZERO( &fds ); FD_SET( pipe_fd, &fds); int rv = select( pipe_fd + 1, &fds, NULL, NULL, &tv ); if( rv == -1 ) perror("select"); else if ( rv > 0 ){ if( FD_ISSET( pipe_fd, &fds ) ) { bytesread = read( pipe_fd, tmpBuff, sizeof( tmpBuff ) ); no_bytes = bytesread; if( bytesread == 0 ) { return -1; } } } if(bytesread > 0 ){ if( strlen( tmpBuff ) > 0 ){ sprintf( buff, "%s", tmpBuff ); tmpBuff[ MAX_BUFFER ] = 0; } } FD_CLR( pipe_fd, &fds ); return 0; } int main() { char buff[ MAX_BUFFER ]; int status; cout << "Ok, jetzt gehts los." << endl; while (1) { if( App1_pid == 0 ) { run_executable( App1_Pipe, App1path, App1_pid ); } int no_bytes = 0; bzero( buff, sizeof( buff ) ); if( App1_pid > 0 ){ read_pipebuffer( buff, no_bytes, PIPE_READ_END(App1_Pipe.pipe_stdout.pipe_fd) ); } if( no_bytes > 0 ){ char *pWord = NULL; pWord = strstr( buff, "Hello"); if(pWord){ if( App2_pid == 0 ) { run_executable( App2_Pipe, App2path, App2_pid ); } } pWord = NULL; pWord = strstr( buff, "kill App1"); if( pWord ){ if( App1_pid ){ kill( App1_pid, SIGKILL ); printf("App1 terminated!"); pid_t w; do { w = waitpid(App1_pid, &status, WUNTRACED | WCONTINUED); if (w == -1) { perror("waitpid"); exit(EXIT_FAILURE); } if (WIFEXITED(status)) { printf("exited, status=%d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("killed by signal %d\n", WTERMSIG(status)); } else if (WIFSTOPPED(status)) { printf("stopped by signal %d\n", WSTOPSIG(status)); } else if (WIFCONTINUED(status)) { printf("continued\n"); } } while (!WIFEXITED(status) && !WIFSIGNALED(status)); App1_pid = 0; } } pWord = NULL; printf("%s\n", buff); } bzero( buff, sizeof( buff ) ); if( App2_pid > 0 ){ read_pipebuffer( buff, no_bytes, PIPE_READ_END(App2_Pipe.pipe_stdout.pipe_fd) ); } if( no_bytes > 0 ){ printf("%s\n", buff); } } return 0; }
#define PIPE_READ_END(x) x[0] #define PIPE_WRITE_END(x) x[1] typedef enum{ acc_read = 0, acc_write = 1 } pipe_access_type; #ifndef MAIN_H_ #define MAIN_H_ #define MAX_PIPE_FD 2 #define MAX_BUFFER 257 typedef struct { int pipe_fd[ MAX_PIPE_FD ]; int fnctl_flags [ MAX_PIPE_FD ]; pipe_access_type pipe_access; } pipe_stdin_type, pipe_stdout_type, pipe_stderr_type; typedef struct{ pipe_stderr_type pipe_stderr; pipe_stdin_type pipe_stdin; pipe_stdout_type pipe_stdout; } pipe_type; int run_executable( pipe_type &child_pipe, const char* progname, int &child_pid ); int read_pipebuffer( char* buff, int &no_bytes, int pipe_fd ); #endif /* MAIN_H_ */
App1...
#include "main.h" #include <iostream> using namespace std; int main(){ while(1){ cout << "******Hello" << endl; sleep(10); cout << "******App1" << endl; sleep(10); cout << "******kill App1" << endl; sleep(10); cout << "******Yeah" << endl; } return 0; }
App2...
#include "main.h" #include <iostream> using namespace std; int main(){ while(1){ cout << "******HI!!!!!" << endl; sleep(40); cout << "******App2" << endl; } return 0; }
Gruß
Franky
-
Naja, bei einem
tv.tv_sec = tv.tv_usec = 0;
kehrt select sofort zurück...
und die äußere while(1)-Schleife macht den Rest.
Probier maltv.tv_sec = tv.tv_usec = 1;
PS:
Liefert vfork() nicht undefiniertes Verhalten, wenn danach im Kind kein exec* nachfolgt ?
Also sollte da nicht ein normales fork() stehen ?lg XOR
-
xor schrieb:
Naja, bei einem
tv.tv_sec = tv.tv_usec = 0;
kehrt select sofort zurück...
und die äußere while(1)-Schleife macht den Rest.
Probier maltv.tv_sec = tv.tv_usec = 1;
Ok, werd ich mal machen.....bis gleich.
xor schrieb:
PS:
Liefert vfork() nicht undefiniertes Verhalten, wenn danach im Kind kein exec* nachfolgt ?
Also sollte da nicht ein normales fork() stehen ?lg XOR
mit vfork...
1.)pid = vfork(); //das kind if( pid == 0){ .... } //der Vater if( pid > 0){ ... } //nur der Vater.... ... ...
den mit fork...
2.)pid = fork(); //das kind if( pid == 0){ .... } //der Vater if( pid > 0){ ... } //das Kind und der Vater.... ... ...
würde dann nicht mit fork die while im Kind als auch im Vater laufen?
Gruß
-
Ich beziehe mich mit vfork auf seine Beschreibung
The vfork() function has the same effect as fork(), except that the behaviour is undefined if the process created by vfork() either modifies any data other than a variable of type pid_t used to store the return value from vfork(), or returns from the function in which vfork() was called, or calls any other function before successfully calling _exit() or one of the exec family of functions.
Soweit ich weiß muss fork() den gesamten Prozess duplizieren, während vfork() dies nicht zwingend machen muss, weil unmittelbar danach eine exec* den Prozess neu lädt oder eben exit() folgen muss. vfork() kann aus einem Prozess zwei machen, die den gleichen Speicher benutzen (geht sehr schnell), weil einer der beiden Prozesse garantiert, dass er sich selbst durch den Aufruf von exec* wieder einen neuen Speicher sucht und den anderen nicht verändert. In deinem Code veränderst du aber nach vfork() Variablen und rufst System-Funktionen auf ... das wiederspricht eben der vfork-Definition.
pid = fork(); // oder vfork(); //das kind if( pid == 0){ .... exec*(...); // Kind ist jetzt ein anderes Programm und wird hier nicht mehr zurückspringen } //der Vater if( pid > 0){ ... } // nur noch der Vater
PS: Ich gestehe aber selber vfork noch nie aktiv eingesetzt zu haben (eben wegen seiner Eigenschaften und weil ich immer noch etwas anderes vor exec zu tun hatte). Es ist auch bekannt dass auf manchen Systemen vfork() == fork() ist und somit keine Seiteneffekte hat ... man kann sich eben nur nicht darauf verlassen
lg XOR
-
Hi,
ja, aber wie stelle ich den sicher, das der nachfolgende Code nur vom Vater ausgeführt wird? Also "nur der Vater..." und nicht "Vater und Kind"... oder habe ich da was nicht verstanden?
Gruß
-
FrankTheFox schrieb:
ja, aber wie stelle ich den sicher, das der nachfolgende Code nur vom Vater ausgeführt wird? Also "nur der Vater..." und nicht "Vater und Kind"...
Indem Du das Kind rechtzeitig beendest?
-
The exec family of functions shall replace the current process image with a new process image. The new image shall be constructed from a regular, executable file called the new process image file. There shall be no return from a successful exec, because the calling process image is overlaid by the new process image.
Wenn dein Programm exec aufruft und dieser Aufruf erfolgreich war, ist dein ursprüngliches (Kind-)Programm bereits beendet, weil exec deinen Prozess durch den neu geladenen ersetzt hat. Nur PID bleibt gleich (damit du im Vater zB. darauf warten kannst bis das andere Programm beendet ist).
pid = fork(); if(pid == 0) { exec*(...); printf("exec failed"); // wird nur ausgeführt wenn exec fehlschlägt exit(1); }
-
Hi,
ja, ich hatte gesehen, das folgendes möglich ist:
PC could be executed by both parent and child.
Das hatte ich vermeiden wollen....//"Sane Structured" use of a fork() call. #include <sys/types.h> #include <unistd.h> int main() { pid_t pid; ... code P_B if((pid = fork()) > 0) { /* Parent process */ ... code P_A } else if (pid == 0) { /* Child process */ ... code C_A } else { /* Parent process, fork() failed */ ... code P_AE } ... code PC } /* You should always use a fork() in the above structured manner to avoid as many problems as possible. Concurrent programs are very hard to get correct and to debug compared to non-parallel programs. In the above pseudo code: Code: P_B (Before fork) is only executed by the parent (child does not exist yet). P_A (After fork) is only executed by the parent (child now exists) C_A (After fork) is only executed by the child. P_AE (After fork, that had an Error) is only executed by the parent if the fork had an error (no child exists). PC could be executed by both parent and child. It is "bad" practice to have a child ever leave code C_A and execute code PC. The child should either make an exec() call in code C_A or an exit() call. */
Aber dank eurer Hilfe und de Seite auf der eigentlich das gleiche gesagt wurde, ist der fork mit einem exec die Garantie, as PC nicht eintritt.
Danke!