Flujos estándares y redirección


Flujos estándares y redirección

Un proceso toma y escribe datos desde y hacia el exterior. El shell, por ejemplo, lee caracteres del teclado e imprime caracteres en la pantalla. En UNIX, los procesos se comunican con el exterior a través de flujos (streams).

Conceptualmente, un flujo es una ristra de bytes que se puede ir leyendo o sobre la que se puede escribir caracteres. Un flujo puede ser un fichero ordinario, o estar asociado a un dispositivo. Cuando se lee del teclado es porque previamente se ha abierto como flujo de caracteres del que leer. Un proceso, cuando muestra algo por pantalla, está escribiendo caracteres a un flujo de salida.

Entrada, salida y error estándares

Los procesos lanzados por un procesador de órdenes (un shell) utilizan dos flujos de particular interés: la entrada estándar y la salida estándar. La entrada estándar es utilizada para recoger información, y la salida estándar para enviar información al exterior.

La entrada estándar suele ser el teclado. La salida estándar suele ser la pantalla. Por ejemplo, cuando se ejecuta ls, este programa nos muestra los ficheros del directorio actual escribiendo los caracteres necesarios sobre la salida estándar (que suele ser la pantalla). Los flujos estándares pueden ser redirigidos a otros ficheros.

Existe también el llamado error estándar, flujo donde se vierten los mensajes de error. Habitualmente coincide con la salida estándar, pero se considera un flujo diferente.

Utilización en un programa en C

La entrada y la salida estándares en UNIX son utilizables en forma de sendos ficheros que están abiertos desde el inicio de la ejecución del programa. Como ya sabrán, cuando se abre un fichero con open se devuelve un descriptor de fichero (file descriptor), que es un número entero que se empleará en posteriores llamadas a las funciones de manejo de ficheros como read o write.

En UNIX siempre se cumple que la entrada estándar tiene el descriptor de valor 0, y la salida estándar el de valor 1.

Redirección

Para redirigir la entrada o la salida hay que conseguir abrir el fichero de redirección de forma que el sistema le asigne el handle 0 ó 1. ¿Cómo lograr esto? Pues teniendo en cuenta que el algoritmo de la llamada open reserva el primer descriptor disponible, empezando a explorar desde el número cero.

Esto significa que si cerramos la salida estándar (descriptor número 1), el siguiente open que se realice asignará al fichero abierto el descriptor 1, quedando automáticamente reasignada la salida estándar. Sirva de ejemplo este código:

close (1);
open ("pepe.txt",O_CREAT,0777);
printf("Estoy escribiendo en pepe.txt\n");

Cualquier nueva operación sobre la salida estándar se dirigirá al fichero "pepe.txt". (Suponiendo que el descriptor 0 no esté libre).

Preservar el antiguo flujo estándar: función dup

A veces conviene preservar el fichero de entrada o salida estándar actual, para restituirlo en el futuro. Para ello se emplea la llamada dup, que duplica un fichero ya abierto, esto es, lo vuelve a abrir y le reserva otro descriptor disponible.

Sintaxis: int dup (int handle);

Ejemplo:

		
int guardado = dup(1);// preserva la salida estándar

/* Realiza la redirección */
close (1);			
open ("pepe.txt",O_CREAT,0777);

... trabajamos con la salida estándar redirigida ...

/* Restituye la antigua salida estándar */

close(1);		// Cierra la actual
dup(guardado);	// Duplica el guardado
			// (le asigna el descriptor 1)
close(guardado);	// Cierra el guardado (no hace más falta)