Pregunta

estoy poniendo en práctica la tubería en un sistema de archivos simulado en C ++ (con su mayoría C). Que necesita para ejecutar comandos en el shell de acogida, sino realizar la tubería de sí mismo en el sistema de archivos simulado.

Me podría lograr esto con las llamadas pipe(), fork(), y del sistema system(), pero yo prefiero usar popen() (que se ocupa de la creación de una tubería, un proceso que se bifurcan, y pasando un comando de la cáscara). Esto puede no ser posible debido a que (creo) que necesito para ser capaz de escribir del proceso padre de la tubería, leer en el extremo proceso hijo, escribir la parte posterior salida del niño, y finalmente leer que la producción de los padres. La página del manual para popen() en mi sistema dice un tubo bidireccional es posible, pero mi código necesita ejecutarse en un sistema con una versión más antigua soportar tuberías solamente unidireccionales.

Con las llamadas separadas anteriores, que pueden abrir / cerrar tuberías para lograr esto. Es que es posible con popen()?

Para un ejemplo trivial, para ejecutar lo que necesito ls -l | grep .txt | grep cmds a:

  • Abrir un tubo y proceso para ejecución ls -l en el host; leer su posterior salida
  • Tubería de la salida de la espalda ls -l a mi simulador
  • Abrir un tubo y proceso para ejecución grep .txt en el host en la salida por tuberías de ls -l
  • Tubería la salida de esta vuelta al simulador (pegado aquí)
  • Abrir un tubo y proceso para ejecución grep cmds en el host en la salida por tuberías de grep .txt
  • Tubería la salida de este de nuevo al simulador y imprimirlo

hombre popen

A partir de Mac OS X:

  

'abre' La función de un popen()   proceso creando un bidireccional   tubería, bifurcar, e invocando la cáscara.   Cualquier corriente abierta por popen() anterior   llamadas en el proceso principal están cerrados   en el nuevo proceso hijo.   Históricamente, se implementó popen()   con un tubo unidireccional; por lo tanto,   muchas implementaciones de popen() solamente   permitir que el argumento de modo para especificar   leer o escribir, no ambas. Porque   popen() ahora se implementa utilizando una   tubo bidireccional, el argumento de modo   puede solicitar un flujo de datos bidireccional.   El argumento de modo es un puntero a una   terminada en nulo cadena que debe ser   'R' para la lectura, 'w' para escribir, o   'R +' para la lectura y la escritura.

¿Fue útil?

Solución

parece haber respondido a su propia pregunta. Si sus necesidades de código para trabajar en un sistema más antiguo que no admite tuberías bidireccionales de apertura popen, entonces usted no será capaz de utilizar popen (al menos no el que está incluido).

La verdadera pregunta sería acerca de las capacidades exactas de los sistemas más antiguos de que se trate. En particular, no su apoyo pipe crear tuberías bidireccionales? Si tienen un pipe que puede crear un tubo bidireccional, pero popen que no, entonces me gustaría escribir la corriente principal del código de uso popen con un tubo bidireccional, y suministran una implementación de popen que puede utilizar un tubo bidireccional que se compila en una utilizado cuando sea necesario.

Si necesita para apoyar los sistemas suficientemente mayor que pipe sólo es compatible con tubos unidireccionales, a continuación, que está bastante atascado con el uso de pipe, fork, dup2, etc., por su cuenta. Yo probablemente todavía terminar con esto en una función que las obras casi como una versión moderna de popen, pero en lugar de devolver un identificador de archivo, rellenos en una estructura pequeña con dos identificadores de archivos, uno para los niños de stdin, el otro para stdout del niño.

Otros consejos

Me gustaría sugerir a escribir su propia función para hacer la tubería / bifurcación / sistema-ción para usted. Usted podría tener la función de generar un proceso de retorno y de lectura / escritura de descriptores de archivo, como en ...

typedef void pfunc_t (int rfd, int wfd);

pid_t pcreate(int fds[2], pfunc_t pfunc) {
    /* Spawn a process from pfunc, returning it's pid. The fds array passed will
     * be filled with two descriptors: fds[0] will read from the child process,
     * and fds[1] will write to it.
     * Similarly, the child process will receive a reading/writing fd set (in
     * that same order) as arguments.
    */
    pid_t pid;
    int pipes[4];

    /* Warning: I'm not handling possible errors in pipe/fork */

    pipe(&pipes[0]); /* Parent read/child write pipe */
    pipe(&pipes[2]); /* Child read/parent write pipe */

    if ((pid = fork()) > 0) {
        /* Parent process */
        fds[0] = pipes[0];
        fds[1] = pipes[3];

        close(pipes[1]);
        close(pipes[2]);

        return pid;

    } else {
        close(pipes[0]);
        close(pipes[3]);

        pfunc(pipes[2], pipes[1]);

        exit(0);
    }

    return -1; /* ? */
}

Se puede añadir cualquier funcionalidad que necesita en ese país.

En una de netresolve backends Estoy hablando con un guión y por lo tanto tengo que escribir a su stdin y leer desde su stdout. La siguiente función se ejecuta un comando con entrada y salida estándar redirigido a una tubería. Se puede utilizar y adaptar a su gusto.

static bool
start_subprocess(char *const command[], int *pid, int *infd, int *outfd)
{
    int p1[2], p2[2];

    if (!pid || !infd || !outfd)
        return false;

    if (pipe(p1) == -1)
        goto err_pipe1;
    if (pipe(p2) == -1)
        goto err_pipe2;
    if ((*pid = fork()) == -1)
        goto err_fork;

    if (*pid) {
        /* Parent process. */
        *infd = p1[1];
        *outfd = p2[0];
        close(p1[0]);
        close(p2[1]);
        return true;
    } else {
        /* Child process. */
        dup2(p1[0], 0);
        dup2(p2[1], 1);
        close(p1[0]);
        close(p1[1]);
        close(p2[0]);
        close(p2[1]);
        execvp(*command, command);
        /* Error occured. */
        fprintf(stderr, "error running %s: %s", *command, strerror(errno));
        abort();
    }

err_fork:
    close(p2[1]);
    close(p2[0]);
err_pipe2:
    close(p1[1]);
    close(p1[0]);
err_pipe1:
    return false;
}

https://github.com/crossdistro/netresolve /blob/master/backends/exec.c#L46

(I utiliza el mismo código en popen simultánea leer y escribir )

No hay necesidad de crear dos tubos y perder un descriptor de fichero en cada proceso. Sólo tiene que utilizar un enchufe en su lugar. https://stackoverflow.com/a/25177958/894520

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top