es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo enviar datos a través de STDIN desde el proceso padre al proceso bisnieto (PIPES/FORK)

Tengo 4 procesos. Parent -> Proceso A (hijo de parent) -> Proceso B (hijo de proceso A) -> Proceso C (hijo de proceso B). Parent obtiene stdin del usuario, lo analiza y lo envía como argumentos al hijo Proceso A y ejecuta un programa en c++ utilizando execv. Luego, proceso A utiliza esos argumentos y emite algo a stdout. Usando pipes y dup2, proceso A envía la salida a stdin de un script en python que se ejecuta en el Proceso B. Finalmente, la salida de stdout del proceso B es stdin de otro programa en c++ en el Proceso C.

Ahora bien, el programa que se ejecuta en Proceso C también necesita recibir entrada stdin (como cuando el usuario la escribe en la terminal). Sin embargo, no puedo enviar esos comandos al Proceso C desde el proceso padre. El comando de entrada simplemente entra en el proceso padre, y el padre básicamente envía lo que analiza correctamente al proceso A a través del pipe.

El proceso padre obtiene la entrada de stdin de esta manera y analiza la cadena y la envía al hijo:

//proceso padre
Parser P;
while (!std::cin.eof()) {
             std::string line;
             std::getline(std::cin, line);

       arguments = P.BeginParsing(line);
              if (arguments.size() > 0) {
                  for (int k = 0; k < 4; k++) {
                      finalArguments[k] = arguments[k];
                  }

                  close(fd[0]);
                  write(fd[1],finalArguments,4*sizeof(int));
                  close(fd[1]);
              }
 }

¿Cómo enviamos datos desde la entrada estándar del proceso padre hasta el bisnieto básicamente, mientras que el bisnieto obtiene la entrada de stdin de su padre? Cualquier ayuda sería apreciada.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para enviar datos del stdin del Padre al bisnieto y permitir que el bisnieto reciba stdin de su padre, necesitamos crear tuberías adicionales entre los procesos.

    Primero, necesitamos modificar el código en el Proceso C para leer desde una tubería como entrada del stdin en lugar de directamente desde la terminal del usuario. Esto se puede hacer utilizando un setup similar de tubería y dup2 a lo que hicimos en el Proceso A:

    //Proceso C
    close(fd[1]); //cerrar ext. de escritura de la tubería desde el proceso B
    dup2(fd[0], STDIN_FILENO); //redirigir stdin para leer la ext. de lectura de la tubería desde el proceso B
    close(fd[0]); //cerrar ext. de lectura de la tubería desde el proceso B
    
    //crear segunda tubería para comunicación con el padre
    int fd2[2];
    pipe(fd2);
    
    if(fork() == 0){
        //Proceso D
        close(fd2[1]); //cerrar ext. de escritura de la segunda tubería
        dup2(fd2[0], STDIN_FILENO); //redirigir stdin para leer la ext. de lectura de la segunda tubería
        close(fd2[0]); //cerrar ext. de lectura de la segunda tubería
    
        //ejecutar programa C++ con argumentos procesados
        execv(path, args);
    
    } else {
        //Proceso C
        close(fd2[0]); //cerrar ext. de lectura de la segunda tubería
        while(1){
            //leer entrada de proceso B, enviar salida a proceso D
            char buffer[1024];
            int numRead = read(STDIN_FILENO, buffer, 1024);
            if(numRead <= 0) break;
    
            write(fd2[1], buffer, numRead);
        }
        close(fd2[1]); //cerrar ext. de escritura de la segunda tubería
    }
    

    Luego, necesitamos crear una tercera tubería para la comunicación entre el proceso Padre y el Proceso C. Podemos modificar el código en el proceso Padre para usar esta nueva tubería para enviar entrada directamente al Proceso C:

    //proceso Padre
    Parser P;
    int fd3[2];
    pipe(fd3);
    while (!std::cin.eof()) {
        std::string line;
        std::getline(std::cin, line);
    
        arguments = P.BeginParsing(line);
        if (arguments.size() > 0) {
            for (int k = 0; k < 4; k++) {
                finalArguments[k] = arguments[k];
            }
    
            close(fd[0]); //cerrar ext. de lectura de la tubería hacia el proceso A
            write(fd[1],finalArguments,4*sizeof(int)); //enviar argumentos al proceso A
            close(fd[1]); //cerrar ext. de escritura de la tubería hacia el proceso A
    
            //enviar entrada directamente al proceso C utilizando la nueva tubería
            close(fd3[0]); //cerrar ext. de lectura de la nueva tubería
            write(fd3[1], line.c_str(), line.length()); //enviar entrada al proceso C
            close(fd3[1]); //cerrar ext. de escritura de la nueva tubería
        }
    }
    

    Finalmente, necesitamos modificar el código en el Proceso B para leer desde la tubería hacia el Proceso C como entrada del stdin en lugar de directamente desde el Proceso A. Podemos utilizar otro setup de tubería y dup2 para lograr esto:

    //Proceso B
    close(fd[1]); //cerrar ext. de escritura de la tubería desde el proceso A
    dup2(fd[0], STDIN_FILENO); //redirigir stdin para leer la ext. de lectura de la tubería desde el proceso A
    close(fd[0]); //cerrar ext. de lectura de la tubería desde el proceso A
    
    //crear nueva tubería para comunicación con el proceso C
    int fd2[2];
    pipe(fd2);
    
    if(fork() == 0){
        //Proceso C
        close(fd2[1]); //cerrar ext. de escritura de la nueva tubería
        dup2(fd2[0], STDIN_FILENO); //redirigir stdin para leer la ext. de lectura de la nueva tubería
        close(fd2[0]); //cerrar ext. de lectura de la nueva tubería
    
        //ejecutar programa C++ con argumentos procesados
        execv(path, args);
    } else {
        //Proceso B
        close(fd2[0]); //cerrar ext. de lectura de la nueva tubería
        while(1){
            //leer entrada del proceso A, enviar salida al proceso C
            char buffer[1024];
            int numRead = read(STDIN_FILENO, buffer, 1024);
            if(numRead <= 0) break;
    
            write(fd2[1], buffer, numRead);
        }
        close(fd2[1]); //cerrar ext. de escritura de la nueva tubería
    }
    

    Con estas modificaciones, el proceso Padre puede enviar entrada tanto al Proceso A como al Proceso C, permitiendo que el Proceso C reciba entrada de su padre.

Comments are closed.