Wie hole ich mir die Ausgabe eines Programms?



  • Hi,

    ich hoffe der Thread ist hier richtig.

    Ich habe folgendes Problem: MPlayer, der aus meinem C-Programm gefork()-exec()ed wurde, schmeißt immer wieder Ausgaben nach stdout, die ich gerne mit dem gleichen C-Programm lesen würde. In ner Shell macht man das ja mit Piping aber in C?

    Hier mal, was ich bisher schon habe:

    // fork MPlayer
    mplayers_pid=fork();
    if(mplayers_pid < 0) {
     ...
    }
    else if(mplayers_pid == 0) {
    	// allright, before starting mplayer, redirect its output so we can read it!
    	int fd;
    	if((fd = open(_MPLAYER_OUTPUT_PIPE, O_RDWR | O_CREAT, S_IWUSR))==-1){
    		perror("open");
    		exit(0);
    	}
    	dup2(fd, STDOUT_FILENO);
    	close(fd); // is not needed anymore...
    
    	execlp("mplayer", "mplayer", "-input", "file="_MPLAYER_REMOTE_PIPE, "-idle", "-msglevel", "all=4", NULL);
    	exit(0);
    }
    

    Also wir haben den FileDeskriptor schon mal mit dup2() umgeleitet, aber jetzt müssen wir irgendwie die Daten an den anderen Prozess schicken. Aber das geht, befürchte ich mal, nur über named pipes, also fifos. Das habe ich auch probiert, die andere Seite öffnet die fifo mit:

    int mplayer_output;
    // ...
    mplayer_output = open(_MPLAYER_OUTPUT_PIPE, O_RDONLY|O_NONBLOCK);
    if(mplayer_output == -1)
     perror("fopen");
    

    Später liest dann dieser Prozess immer, wenn MPlayer was reingeschrieben hat, von der Fifo mit:

    char line[64] = "";
    while(read(mplayer_output, line, 63)>0) {
    	line[63] = 0;
    	printf("ANSWER: %s\n",line);
    }
    

    Das Problem ist dabei, dass weder MPlayer, noch mein C-Programm mehr reagieren, sobald MPlayer was in die Fifo schickt. Wenn ich den FileDeskriptor für das C-Programm mit O_NONBLOCK öffne, reagiert immerhin das C-Programm, aber MPlayer nicht; wenn ich den FileDeskriptor für MPlayer auch noch mit O_NONBLOCK öffne, reagiert MPlayer immer noch nicht!

    Was mache ich falsch? Gibt es auch alternativen zur FIFO (das wäre mir lieber ;))

    Über Antworten würde ich mich wirklich sehr freuen!

    MfG,
    voidpointer





  • rüdiger schrieb:

    man: pipe(2)

    Wie kann man pipe() zur Kommunikation zweier Threads nutzen? D.h. woher weiß der eine Thread den File-Deskriptor des anderen?



  • wie wär's, wenn du die man page liest? Genau das wird dort erklärt.



  • Hallo,

    ich haber hier ein kleines Beipsiel:

    static STRING getVacationAdresses( void )
    {
    	STRING	adresses;
    	int		fds[2];
    
    	if( !pipe( fds ) )
    	{
    		pid_t	pid = fork();
    		if( pid == 0 )	// I'm the child
    		{
    			close( fds[0] );	// close unused pipe read
    			dup2( fds[1], 1 );	// redirect stdout to the pipe
    			execlp( "vacation", "vacation", "-l", NULL );
    			exit( 0 );	// should never happen
    		}
    		else if( pid > 0 )
    		{
    			char buffer[1024];
    			size_t	count;
    			close( fds[1] );	// close unused pipe write
    			while( true )
    			{
    				count = read( fds[0], buffer, sizeof( buffer ) -1 );
    				if( count > 0 )
    				{
    					buffer[count] = 0;
    					adresses += buffer;
    				}
    				else
    					break;
    			}
    		}
    	}
    
    	return adresses;
    }
    

    Der Typ STRING müsste halt bei Euch durch std::string ersetzt werden.

    EDIT: Der Aufruf der dup2-funktion musste geändert werden, ich hatte die beiden Parameter vertauscht und es funktionierte bei mir nur zufällig.

    mfg Martin



  • Man koennte auch popen benutzen.



  • knivil schrieb:

    Man koennte auch popen benutzen.

    Das wäre natürlich einfacher gewesen. Macht aber nix, so spar ich mir den Shellaufruf und ich hab was gelernt.

    mfg Martin


Anmelden zum Antworten