El programa corto a continuación tiene la intención de iterar sobre argv pasado desde la línea de comando y ejecutar cada argumento. Esta no es mi tarea, sino que es algo que estoy haciendo en preparación para hacer mi tarea.¿Entiendo cómo funcionan los descriptores de archivos Unix en C?
El primer argumento obtiene la entrada de STDIN y STDOUT, y escribe en una tubería. Al final de cada iteración (excepto la última), los descriptores de archivo se intercambian, de modo que la tubería escrita por el último ejecutivo se leerá a partir de la siguiente. De esta manera me propongo, por ejemplo, para
./a.out /bin/pwd /usr/bin/wc
imprimir solo la longitud del directorio de trabajo. Código sigue
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
main(int argc, char * argv[]) {
int i;
int left[2], right[2], nbytes; /* arrays for file descriptors */
/* pointers for swapping */
int (* temp);
int (* leftPipe) = left;
int (* rightPipe) = right;
pid_t childpid;
char readbuffer[80];
/* for the first iteration, leftPipe is STDIN */
leftPipe[0] = STDIN_FILENO;
leftPipe[1] = STDOUT_FILENO;
for (i = 1; i < argc; i++) {
/* reopen the right pipe (is this necessary?) */
pipe(rightPipe);
fprintf(stderr, "%d: %s\n", i, argv[i]);
fprintf(stderr, "%d %d %d %d\n", leftPipe[0], leftPipe[1], rightPipe[0], rightPipe[1]);
if ((childpid = fork()) == -1) {
perror("fork");
exit(1);
}
if (childpid == 0) {
/* read input from the left */
close(leftPipe[1]); /* close output */
dup2(leftPipe[0], STDIN_FILENO);
close(leftPipe[0]); /* is this necessary? A tutorial seemed to be doing this */
/* write output to the right */
close(rightPipe[0]); /* close input */
dup2(rightPipe[1], STDOUT_FILENO);
close(rightPipe[1]);
execl(argv[i], argv[i], NULL);
exit(0);
}
wait();
/* on all but the last iteration, swap the pipes */
if (i + 1 < argc) {
/* swap the pipes */
fprintf(stderr, "%d %d %d %d\n", leftPipe[0], leftPipe[1], rightPipe[0], rightPipe[1]);
temp = leftPipe;
leftPipe = rightPipe;
rightPipe = temp;
fprintf(stderr, "%d %d %d %d\n", leftPipe[0], leftPipe[1], rightPipe[0], rightPipe[1]);
}
}
/* read what was last written to the right pipe */
close(rightPipe[1]); /* the receiving process closes 1 */
nbytes = read(rightPipe[0], readbuffer, sizeof(readbuffer));
readbuffer[nbytes] = 0;
fprintf(stderr, "Received string: %s\n", readbuffer);
return 0;
}
ACTUALIZACIÓN: en todos los casos de prueba a continuación que había utilizado originalmente/bin/wc, pero que WC reveiled que el inodoro no es en absoluto en el que pensé. Estoy en el proceso de modificar los resultados.
La salida en un caso trivial (./a.out/bin/pwd) es como se esperaba:
1: /bin/pwd
Received string: /home/zeigfreid/Works/programmatical/Langara/spring_2012/OS/labs/lab02/play
La salida de la ejecución de este programa con el primer ejemplo (./a.out/bin/pwd/usr/bin/wc):
1: /bin/pwd
0 1 3 4
3 4 0 1
2: /bin/wc
en ese punto, se bloquea el terminales (tal vez esperando en la entrada).
Como puede ver, la secuencia no se está recibiendo. Lo que imagino es que he hecho algo mal arriba, ya sea al intercambiar punteros, o que no entiendo los descriptores de archivos de Unix. Mi tarea, al final, será interpretar tubos arbitrariamente largos, y esta es una de las ideas que tuve para resolver el problema. Tengo problemas para juzgar si estoy en el camino correcto de ladrar en un árbol. ¿Comprendo los descriptores de archivos de Unix?
ACTUALIZACIÓN:
Correr con/bin/ls como el segundo argumento, que tiene el siguiente resultado (los números son los descriptores de fichero en varios puntos):
1: /bin/pwd
0 1 3 4
0 1 3 4
3 4 0 1
2: /bin/ls
3 4 5 6
Received string: a.out
log
pipe2.c
play.c
@
Hay Todavía hay algo de basura al final, pero ahora estoy más preocupado porque no entiendo los indicadores. Sin embargo, estos dos comandos son independientes entre sí, realmente no hacen uso de la tubería.
ACTUALIZACIÓN: el carácter de basura fue por no cerrar la cadena. Ahora lo cierro, y no hay basura.
me gustaría sugerir cambiar toda su 'printf (...)' 'pone en fprintf (stderr , ...) '. Mezclar IO estándar ('printf (3)') con las rutinas de nivel inferior ('pipe (2)', 'dup2 (2)', 'close (2)') es más problemático de lo que vale. – sarnold
¡Debidamente anotado! Me imagino que la férula estaría de acuerdo. – Ziggy
No termina la cadena antes de imprimirla, esto explica la basura. Pruebe 'readbytes [nbytes] = 0' después de' leer'. –