2011-02-12 11 views
5
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 

int 
main(int argc, char **argv) 
{ 
    int pfds[ 2], i; 
    size_t pbytrd; 
    pid_t childpid; 
    char buffer[ 200]; 

    pipe(pfds); 
    if((childpid = fork()) == -1) 
    { 
      perror("fork error: "); 
      exit(1); 
    } 
    else if(childpid == 0) 
    { 
      close(pfds[ 0]); 
      dup2(pfds[1], 1); 
      close(pfds[ 1]); 
      for(i = 0; i < 10; i++) 
       printf("Hello..."); 
      execlp("xterm","xterm","-e","./sample_a", (char *) 0); 
      exit(0); 
} 
else 
{ 

     close(pfds[ 1]); 
     for(; ;) 
     { 
      if((pbytrd = read(pfds[ 0], buffer, sizeof(buffer))) == -1) 
      { 
       perror(" read error: "); 
       exit(1); 
      } 
      else if(pbytrd == 0) 
      { 

       write(fileno(stdout), "Cannot read from pipe...\n", strlen("Cannot read from pipe...\n")); 
       exit(0); 
      } 
      else 
      { 
       write(fileno(stdout), "MESSAGE: ", strlen("MESSAGE: ")); 
       write(fileno(stdout), buffer, pbytrd); 
      } 
     }  
} 
return(0); 

}dup2() y exec()

Mi código es sample_a.c a continuación:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 

int 
main(int argc, char **argv) 
{ 
     int i; 
     for(i= 0; i< 10; i++) 
     write(fileno(stdout), "Hello...", strlen("Hello...")); 
    return(0); 
} 

En el código anterior, lo que realmente quiero hacer es: 1) redirección salida desde el proceso secundario a la tubería y que el padre lea desde la tubería e imprima en stdout.

Soy capaz de redirigir la salida del proceso hijo ("printf") de stdout a la tubería, pero no puedo redirigir el proceso hijo de execlp, xterm, salida a la tubería.

¿Alguien me puede ayudar esto?

Respuesta

4

xterm es un emulador de terminal. Ejecuta el programa que proporcionó (sample_a), conectando sus entradas y salidas consigo mismo, de modo que el programa recibe la entrada del usuario en su entrada estándar e imprime al usuario cualquier cosa que envíe a sus salidas estándar y de error.

Lo que está haciendo su programa es conectar la salida xterm a la tubería e intentar leer eso. Pero xterm es un programa GUI, normalmente no escribe datos en sus salidas. Tal vez no esté realmente claro qué es exactamente lo que estás tratando de lograr.

Si se quita la parte xterm, debería funcionar como se espera, es decir, el proceso padre verá lo sample_a escribe a la salida.

 execlp("./sample_a", "./sample_a", (char *) 0); 
+0

Acepto, si elimino la parte xterm, funcionará. Es una pregunta de programación que vi en uno de los sitios web de la universidad. El ejercicio consiste en aceptar la entrada del usuario en la ventana xterm y mostrar la salida en xterm, pero cualquier error (perror) debe imprimirse en la ventana de la terminal desde donde se llama. Entonces, ¿no hay forma de que xterm pueda comunicarse nuevamente con la ventana de la terminal? En realidad, esta es una pequeña parte del gran problema (problema de 5-6 páginas). Espero que esto ayude –

1

xterm no tiene salida, por lo que no hay forma de redirigirlo a ninguna parte. xterm ejecuta un elemento secundario y redirige la salida del elemento secundario a sí mismo, de modo que si desea redirigir la salida del elemento a otro lugar que no sea el xterm, deberá hacerlo usted mismo en el elemento secundario, DESPUÉS de que xterm lo inicie. La forma más fácil de hacer eso es probablemente tener xterm start a shell y usar redirección de shell. Para redirigir stderr solo para el niño, que tendría que utilizar algo como:

execlp("xterm", "xterm", "-e", "/bin/sh", "-c", "./sample_a 2>somewhere", 0); 

reemplazando somewhere con algo apropiado. Suponiendo que desea capturar eso en su programa original, probablemente desee crear un fifo temporal con tempnam (3) y mkfifo (3) y abrirlo para leer en su padre. Debe crearlo antes de bifurcarlo y abrirlo después de bifurcar, ya que la apertura se bloqueará hasta que se ejecute el shell y se abrirá el final de escritura. Una vez que se complete la apertura, puede eliminar la fifo y leer de la fifo ahora sin nombre.

1

Me enfrenté a una situación similar. Mi objetivo era enviar cierta información del proceso secundario que se ejecuta en un xterm. Como también se informó anteriormente, no pude usar dup2. Una solución para esto es pasar el fd al nuevo binario como xterm args.

Un enfoque (sin comprobaciones de errores para abreviar) es

if (childpid == 0) 
{ 
    /* child closes read*/ 
    close(pipeFD[0]); 
    char writeFD[10]; // do consider space for '\0' 
    /* Extract the write fd and put it in a char buffer 
     make compatible as per execlp args */ 
    sprintf(writeFD, "%d", pipeFD[1]); 
    /* just pass the writeFD as an arg */ 
    execlp("xterm", "xterm", "-e", "./binary", writeFD, (char *) 0)) 

} 
else 
{ 
    /* parent closes write */ 
    close(pipeFD[1]); 
    if((bytesRead = read(pipeFD[0], buf, SIZE)) != -1) 
    { 
     printf("Recieved %s\n", buf); 
     close(pipeFD[0]); 
    } 
} 

En el proceso hijo que se ejecuta en xterm sugirió, extraer el fd

main(int argc, char** argv) { 
    int fd = atoi(argv[1]); 
    write(fd, buf,sizeof(buf)); 
}  

No sé qué dosis dup2 No funciona con xterm, pero esta solución resuelve el requisito.

1

La matriz pipeFD almacena dos descripciones de archivos de entrada y salida, una vez que haya creado una ventana xterm.El proceso secundario no sabe dónde escribir. Así que usted puede utilizar dup2:

dup2(pipeFD[1],100); 
close(pipeFD[1]); 

Asigna el puerto de escritura viejo para un nuevo puerto (otros números también funcionan). Y en el xterm puede escribir en la tubería por

write(100,"something you wanna to write").