Wie starte ich einen Prozess...



  • Hi,

    ich beginne jetzt in der main so....

    int main() {
       int    processId;
       processId = fork();		
       cout << "forked to :  " << processId << endl; 
       if( processId == 0 )		// Create child
       { 
           	execl("/bin/bash","/bin/bash",(char *)0); // Shell starten
       }   
       else if( processId == -1) {
         perror("fork");
       }
       else{ // Parent
         init_server_connection();
         get_client_related_messages(&msgs);
         ...
         return 0;
       }
    }
    

    mit ps xfg

    sehe ich:

    \_ konsole  [..
    |    \_ /bin/bash
    |        \_ ./myApp
    |            \_ /bin/bash
    

    Aber ich sehe doch keine Bash

    Im Terminal sehe nach Client relevanten Ausgaben

    [1]+ Stopped ./myApp
    und dann die Eigabeauforderung! MyApp laüft noch....

    Gruß
    Franky



  • Sobald der Eltern-Pozess beendet wird, werden auch dessen Standard Ein- und Ausgabe-Dateideskriptoren geschlossen. Und da dank fork Eltern- und Kind-Prozess diese gemeinsam nutzen, verwandelt sich der Kind-Prozess in einen Daemon ohne Standard Ein- und Ausgabe. :3 Daher siehst du nichts von der bash. ;3 Wenn du möchtest, dass die bash nach dem Beenden des Eltern-Prozesses noch benutzbar bleibt, kannst du den Spieß umdrehen:

    #include <cstdio>
    #include <unistd.h>
    
    int main()
    {
      int processId = fork();
      if(!processId)
        {
          // do your stuff here
          yiff();
          return 0;
        }
      else if(processId == -1)
        {
          perror("fork");
          return 1;
        }
      else
        {
          execl("/bin/bash", "/bin/bash", NULL);
        }
    }
    

    Jetzt ist der Eltern-Prozess /bin/bash und der Kind-Prozess dein Netzwerk-Dingens. ^^



  • Hi,

    danke, aber ich glaube das Problem liegt woanders....

    int aa = execl("/usr/home/myUsrName/Workpace/myApp",
                   "myApp" ,(char *)0); // App starten
    cout << "aa:  " << aa << endl;
    

    pwd im Ordner "myApp" ergibt:

    /home/myUsrName/Workspace/myApp

    Ich sehe das beim Lauf:

    aa: -1

    Gruß
    Franky



  • FrankTheFox schrieb:

    int aa = execl("/usr/home/myUsrName/Workpace/myApp",
                   "myApp" ,(char *)0); // App starten
    cout << "aa:  " << aa << endl;
    

    pwd im Ordner "myApp" ergibt:

    /home/myUsrName/Workspace/myApp

    Warum ist da dann ein /usr vor dem Pfad? :3 Und ein s fehlt in Workpace . ^^

    Abgesehen davon: Wenn /home/myUsrName/Workspace/myApp der Ordner ist, in dem dein Programm liegt, dann musst du den Programmnamen noch mit dran hängen. Und der gesamte Pfad muss auch im zweiten Argument stehen. Beim /bin/bash -Beispiel hast du das noch richtig gemacht. ;3

    int aa = execl("/home/myUsrName/Workspace/myApp/myApp",
                   "/home/myUsrName/Workspace/myApp/myApp",
                   (char *)0); // App starten
    cout << "aa:  " << aa << endl;
    

    FrankTheFox schrieb:

    Ich sehe das beim Lauf:

    aa: -1

    perror("execl"); sagt dir, wo genau das Problem ist. :3



  • Hi,

    ich habe im Internet folgenden Code gefunden....

    #define READ_END(x) x[0]
    #define WRITE_END(x) x[1]
    
    int run_program (const char* progname,
    		 char* const args[],
    		 char* const env[]) {
      int pipefd_stdin[2];
      int pipefd_stdout[2];
      int pipefd_stderr[2];
    
      if (pipe(pipefd_stdin) == -1) {
        perror("pipe");
      }
      if (pipe(pipefd_stdout) == -1) {
        perror("pipe");
      }
      if (pipe(pipefd_stderr) == -1) {
        perror("pipe");
      }
    
      int subproc = fork ();
      printf("forked to pid %d\n", subproc);
    
      if (subproc == -1) {
        perror("fork");
      } else if (subproc == 0) {
        close(WRITE_END(pipefd_stdin));
        close(READ_END(pipefd_stdout));
        close(READ_END(pipefd_stderr));
    
        dup2(READ_END(pipefd_stdin), STDIN_FILENO);
        dup2(WRITE_END(pipefd_stdout), STDOUT_FILENO);
        dup2(WRITE_END(pipefd_stderr), STDERR_FILENO);
    
        execve(progname, args, env);
    
      } else {
        close(READ_END(pipefd_stdin));
        close(WRITE_END(pipefd_stdout));
        close(WRITE_END(pipefd_stderr));
    
        int i;
        char buff[256];
        char buff2[257];
    
        while ((i = read(READ_END(pipefd_stdout), &buff, sizeof(buff))) != 0) {
          if (i == -1) {
    	perror("read");
          }
          bzero(&buff2, sizeof(buff2));
          memcpy (&buff2, &buff, i);
          printf("%s...", &buff2);
          fflush(0);
        }
      }
    }
    

    wenn ich jetzt nur das Programm aufrufe, also meinen eigentlichen Elterncode rauslasse...

    int main(){
      const char* progname = "/home/myUsrName/Workspace/myApp/myApp"
      void* nullobj = NULL;
      char** args = (char**) &nullobj;
      printf("running...\n");
      run_program (progname, args, args);
    
      while(1){
      ...
    //warte bis taste...
      }
    }
    

    dann klappts (zumindest der Start des Programms). Aber warum?

    Gruß
    Franky



  • Hier wir über eine pipe die Ausgabe den Kind-Prozesses an den Eltern-Prozess weitergeleitet, der diese dann schließlich über die Standard-Ausgabe ausgibt. ^^"

    Wie gesagt, wenn du möchtest, dass dein Kind Prozess benutzbar bleibt, starte ihn im Eltern-Prozess und tu dein Netzwerk Zeugs im Kind-Prozess, wie ich es auf der vorherigen Seite beschreiben habe. Das ist wesentlich einfacher. ;3



  • Hallo,

    ich habe jetzt das so gemacht.... (Wobei ich das mit den Pipes gar nicht so schlecht finde, mich aber frage ob ich das brauche denn die Ausgaben der "Childs" sehe ich ja so auch).

    int main() {
        int pid = fork();
    
        if( pid == 0 ){  //child1!!!!!!!
              cout << "start myApp1................  " << endl; 
    	  int aa = execl("/home/myUsrName/Workspace/myApp1/myApp1,
    		         "/home/myUsrName/Workspace/myApp1/myApp1",
    			 (char *)0); // App starten
    	  cout << "(Fehler) myApp1:  " << aa << endl; 
    	  perror("execl"); 
    	  return (-1);
        }	  	  
        pid = fork();
    
        if( pid == 0 ){  //child!!!!!!!
    	cout << "start myApp2................  " << endl;   
    	int aa = execl("/home/myUsrName/Workspace/myApp2/myApp2,
    		       "/home/myUsrName/Workspace/myApp2/myApp2,
    	  		(char *)0); // App starten
    	cout << "(Fehler)  myApp2  " << aa << endl;
    	perror("execl"); 
    	return (-1);
        }
        //Ab hier dann der parent
    
        //init_server_stuff();  
    
        while(1){
             //code stuff
        }
    
        //close_server_stuff();
    
        return 0;
    }
    

    Im Elternprozess geht die Ausführung nach fork weiter und execl kehrt nicht zurück (ausser wenn ein Fehler auftritt)
    dann macht das Child eine Serververbindung auf während der Elternprozess das nächste "Kind" startet und das macht eine Serververbindung auf. Dann schließlich der Parent der eine Serververbindung aufmacht...

    beide Anwendungen werden gestartet.... und laufen...
    und ich sehe die Ausgaben im Terminal...
    Ich brauche noch nicht einmal den child im Elternprozess starten...

    Wie kann ich den jetzt den z.B. myApp2 stoppen und wieder starten und wie kriege ich mit ob der Prozess auch wirklich gestoppt hat.

    Gruß
    Franky



  • FrankTheFox schrieb:

    Wie kann ich den jetzt den z.B. myApp2 stoppen und wieder starten und wie kriege ich mit ob der Prozess auch wirklich gestoppt hat.

    Das geht mit man: kill(2) und man: waitpid(2).

    Welche Signale du mit kill senden kannst, steht hier: man: signal(7).



  • Hallo,

    danke. ich habe jetzt ein wenig rumgespielt um zu verstehen wie genau fork und exec* funktionert. Das mit den Pipes lässt mir auch keine Ruhe...also
    habe jetzt erstmal

    #define MAX 257
    #define MAX_PIPE_FD 2 
    
    typedef struct {
    	int pipefd_stdin[ MAX_PIPE_FD ];
    	int pipefd_stdout[ MAX_PIPE_FD ];
    	int pipefd_stderr[ MAX_PIPE_FD ];
    } pipe_type;
    
    int run_executable ( pipe_type &child_pipe, 					
    				     const char* progname,
    				     int &child_pid );
    
    int read_pipebuffer( char* buff,  int pipe_fd );
    

    und dann...

    int read_pipebuffer( char* buff, int pipe_fd )
    {
    	char tmpBuff[ MAX -1 ];
    	int i;
    	while( ( i = read( pipe_fd, &tmpBuff, sizeof( tmpBuff ) ) ) != 0 ){
    		if( i == -1 ){
    			perror( "read" );
    			return 0;
    		}
    		bzero( buff, MAX );
    		memcpy( buff, &tmpBuff, i );
    		fflush( 0 );
    	}	
    	return 1;
    }
    

    und...

    int run_executable( pipe_type &child_pipe,					
    				    const char* progname,
    				    int &child_pid )
    {
    	if( pipe( child_pipe.pipefd_stdin ) == -1 ){
    			perror("pipe");
    	}
    	if( pipe( child_pipe.pipefd_stdout ) == -1 ){
    		perror("pipe");
    	}
    	if( pipe( child_pipe.pipefd_stderr ) == -1 ){
    		perror("pipe");
    	}
    
    	int pid = fork();
    	child_pid = pid;
    	if (pid == -1){
    		perror("fork");
    	}
    	else if( pid == 0 ){  //code executed by Child
    		//close write end of standard in
    		close( child_pipe.pipefd_stdin[1] );
    		//close read end of standard out
    		close( child_pipe.pipefd_stdout[0] );
    		//close read end of standard err
    		close( child_pipe.pipefd_stderr[0] );
    		//to make read end of pipe-to-child into standard input.
    		dup2( child_pipe.pipefd_stdin[0], STDIN_FILENO );
    		//to make write end of pipe-to-child into standard out.
    		dup2( child_pipe.pipefd_stdout[1], STDOUT_FILENO );
    		//to make write end of pipe-to-child into standard error.
    		dup2( child_pipe.pipefd_stderr[1], STDERR_FILENO );
    		//run executable
    		execl( progname, progname, (char *)0 );		
    		}
    	else{
    		close( child_pipe.pipefd_stdin[0] ); //read end
    		close( child_pipe.pipefd_stdout[1] ); //write end
    		close( child_pipe.pipefd_stderr[1] ); //write end
    	}
    	return 0;
    }
    

    Ich habe mir eine App gebaut, die nur die Tools startet (ohne Serververbindung selber zu öffnen...)

    int main() {
    const char* app1_name = "/home/myUsrName/Workspace/myApp1/myApp1";
    const char* app2_name = "/home/myUsrName/Workspace/myApp2/myApp2";
    const char* app3_name = "/home/myUsrName/Workspace/myApp3/myApp3";
    
    pipe_type app1_pipe;
    int app1_pid;
    pipe_type app2_pipe;
    int app2_pid;
    pipe_type app3_pipe;
    int app3_pid;
    
    char buff[ MAX ];
    
    while(1){
    
    		cout << "..........................." << endl;
    		//first start app1 (only once)...	
    		if ( waitpid( app1_pid, NULL, WNOHANG ) == -1 ){
    			cout << "kein prozess!!!!!!!!!!!!!!!!!" << endl;
    			run_executable ( app1_pipe, app1_name, app1_pid);	  
    		}		
    		read_pipebuffer( buff, app1_pipe.pipefd_stdout[0] );
    		cout << ";;;;;;;;;;;;;;;;;;;;;;" << endl;
    
    		//printf("%s\n\n", buff);
    
    	}
    }
    

    nur sehe ich nicht ";;;;;;;;;;;;;;;;;;;;;;" obwohl app1 was in die Ausgabe schreibt.

    Was habe ich falsch gemacht?

    Gruß



  • Hi,

    habe jetzt geschafft App1 zu starten, aber nicht App2....

    //User includes
    #include "AccServer.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/frank/workspace/App1/App1";
    const char* App2path = "/home/frank/workspace/App1/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){
    		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 );
    	}
    	else if( pid > 0 ){
    		child_pid = pid;
    		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 = {0};
    
    	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 )
    			{
    				//printf(" App closed!\n");
    				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 ];
    	cout << "Ok, jetzt gehts los." << endl;
    
    	while (1)
    	{
    		if( waitpid( App1_pid, NULL, WNOHANG ) == -1 )
    		{
    			run_executable( App1_Pipe, App1path, App1_pid );
    		}
    		int no_bytes = 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){
    				printf("Hello found!");
    				if( waitpid( App2_pid, NULL, WNOHANG ) == -1 )
    				{
    					printf("vor run_exec...  App2!");
    					run_executable( App2_Pipe, App2path, App2_pid );
    				}
    
    			}
    			pWord = NULL;
    			pWord = strstr( buff, "kill App1");
    			if( pWord ){
    				kill( App1_pid, SIGKILL );
    				printf("App1 terminated!");
    
    			}
    			pWord = NULL;
    			printf("%s\n", buff);
    		}
    
    	}
    	return 0;
    }
    
    //Konsole mit ps axfg   zeigt Prozesse!!!!
    
    #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 ACCSERVER_H_
    #define ACCSERVER_H_
    
    #define MAX_PIPE_FD 2
    #define MAX_BUFFER 257
    
    /*
     * standard streams are preconnected input and output channels
     * between a computer program and its environment (typically a
     * text terminal) when it begins execution.
     */
    
    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 /* ACCSERVER_H_ */
    

    Gruß
    Franky


Anmelden zum Antworten