Al sistema operativo le interesa que los programas estén cómodos. Y por eso ofrece toda una serie de comodidades para que los programas se olviden de las complejidades de la vida. Entre esas abstracciones se encuentran los file descriptors.
Un file descriptor es un numerito provisto por el kernel, usualmente no muy alto, que representa algo a lo que se puede mandar bytes, o desde donde se puede leerlos. En UNIX, muchas cosas pueden verse como file descriptors:
Es decir que si uno aprende a manipular file descriptors, ya casi sabe cómo lidiar con estas entidades que cité.
Las dos operaciones básicas sobre file descriptors son:
Las funciones que presento más arriba son simples y primitivas. Por ejemplo, si el file descriptor está apuntando a un archivo estas funciones mandarán los bytes a disco directamente. Es decir que si escribimos en un ciclo mil veces un byte, se accede mil veces al disco rígido. El uso de un "buffer" intermedio permitiría obtener mucho mayor rendimiento. Para esto y otras cosas, Linux provee algunas funciones de alto nivel que se pueden utilizar en vez de manipular directamente los file descriptors. Estas funciones son las clásicas y estándar del lenguaje C (fread, fwrite, fprintf, etc).
Estas funciones, que son de biblioteca (es decir que no están
implementadas, como las otras, dentro del kernel) manipulan todo mediante un
puntero a una estructura FILE. En el caso de estar
manejando archivos en disco es sabido como obtener un puntero a esta
estructura: fopen("archivo.txt", "r")
. En el caso de querer
usarse estas funciones con un file descriptor que ya se tiene (por ejemplo
una conexión de red) debe utilizarse la función fdopen(). Esta función
provee un puente entre estos dos mundos: recibe un file descriptor y entrega
un puntero a FILE. La otra función puente (en el sentido inverso) es
fileno, que permite obtener el file descriptor de un FILE
ya existente.