Manejo de entrada y salida

Este tema proporciona una introducción a las consideraciones de programación para el manejo de entrada y salida y las subrutinas de manejo de entrada y salida (E/S).

Las subrutinas de biblioteca de E/S pueden enviar datos a o desde dispositivos o archivos. El sistema trata los dispositivos como si fueran archivos de E/S. Por ejemplo, también debe abrir y cerrar un dispositivo al igual que hace un archivo.

Algunas de las subrutinas utilizan la entrada estándar y la salida estándar como sus canales de E/S. Sin embargo, para la mayoría de las subrutinas, puede especificar un archivo diferente para el origen o destino de la transferencia de datos. Para algunas subrutinas, puede utilizar un puntero de archivo a una estructura que contiene el nombre del archivo; para otras, puede utilizar un descriptor de archivo (es decir, el entero positivo asignado al archivo cuando se abre).

Las subrutinas de E/S almacenadas en la biblioteca C (libc.a) proporcionan E/S de corriente. Para acceder a estas subrutinas de E/S de corriente, debe incluir el archivo stdio.h utilizando la sentencia siguiente:
#include <stdio.h>

Algunas de las subrutinas de biblioteca de E/S son macros definidas en un archivo de cabecera y algunas son módulos de objeto de funciones. En muchos casos, la biblioteca contiene una macro y una función que realizan el mismo tipo de operación. Tenga en cuenta lo siguiente al decidir si desea utilizar la macro o la función:

  • No puede establecer un punto de interrupción para una macro utilizando el programa dbx .
  • Las macros suelen ser más rápidas que sus funciones equivalentes porque el preprocesador sustituye las macros por líneas de código reales en el programa.
  • Las macros dan como resultado un código de objeto más grande después de compilarse.
  • Las funciones pueden tener efectos secundarios para evitar.

Los archivos, mandatos y subrutinas utilizados en el manejo de E/S proporcionan las interfaces siguientes:

Nivel bajo
La interfaz de bajo nivel proporciona funciones básicas de apertura y cierre para archivos y dispositivos.
Flujo
La interfaz de secuencia proporciona E/S de lectura y escritura para conductos y FIFO.
Tarea Proc
La interfaz de terminal proporciona salida formateada y almacenamiento intermedio.
Asíncrono
La interfaz asíncrona proporciona E/S y proceso simultáneos.
Idioma de entrada
La interfaz de lenguaje de entrada utiliza los mandatos lex y yacc para generar un analizador léxico y un programa analizador para interpretar E/S.

Interfaces de E/S de bajo nivel

Las interfaces de E/S de bajo nivel son puntos de entrada directos en un kernel, proporcionando funciones como abrir archivos, leer y grabar archivos y cerrar archivos.

El mandato line proporciona la interfaz que permite leer una línea de la entrada estándar y las subrutinas siguientes proporcionan otras funciones de E/S de bajo nivel:

open, openx o creat
Preparar un archivo, u otro objeto de vía de acceso, para leer y escribir mediante un descriptor de archivo asignado
read, readx, readv o readvx
Leer de un descriptor de archivo abierto
write, writex, writev o writevx
Escribir en un descriptor de archivo abierto
Cerrar
Renunciar a un descriptor de archivo

Las subrutinas open y creat configuran entradas en tres tablas del sistema. Un descriptor de archivo indexa la primera tabla, que funciona como un área de datos por proceso a la que pueden acceder las subrutinas de lectura y escritura. Cada entrada de esta tabla tiene un puntero a una entrada correspondiente de la segunda tabla.

La segunda tabla es una base de datos por sistema, o tabla de archivos, que permite compartir un archivo abierto entre varios procesos. Las entradas de esta tabla indican si el archivo estaba abierto para lectura, grabación o como un conducto, y cuándo se cerró el archivo. También hay un desplazamiento para indicar dónde se llevará a cabo la siguiente lectura o grabación y un puntero final para indicar la entrada a la tercera tabla, que contiene una copia del i-nodo del archivo.

La tabla de archivos contiene entradas para cada instancia de una subrutina open o create en el archivo, pero la tabla de inodo sólo contiene una entrada para cada archivo.

Nota: Al procesar una subrutina open o creat para un archivo especial, el sistema siempre llama a la subrutina open del dispositivo para permitir cualquier proceso especial (como rebobinar una cinta o activar un módem preparado para terminal de datos). Sin embargo, el sistema utiliza la subrutina close sólo cuando el último proceso cierra el archivo (es decir, cuando se desasigna la entrada de tabla de i-nodo). Esto significa que un dispositivo no puede mantener o depender de un recuento de sus usuarios a menos que se implemente un dispositivo de uso exclusivo (que impide que se vuelva a abrir un dispositivo antes de su cierre).

Cuando se produce una operación de lectura o grabación, los argumentos del usuario y la entrada de tabla de archivos se utilizan para configurar las variables siguientes:

  • Dirección de usuario del área de destino de E/S
  • Recuento de bytes para la transferencia
  • Ubicación actual en el archivo

Si el archivo al que se hace referencia es un archivo especial de tipo carácter, se llama a la subrutina de lectura o grabación adecuada para transferir datos, así como para actualizar el recuento y la ubicación actual. De lo contrario, la ubicación actual se utiliza para calcular un número de bloque lógico en el archivo.

Si el archivo es un archivo ordinario, el número de bloque lógico debe correlacionarse con un número de bloque físico. No es necesario correlacionar un archivo especial de tipo de bloque. El número de bloque físico resultante se utiliza para leer o grabar el dispositivo adecuado.

Los controladores de dispositivo de bloque pueden proporcionar la capacidad de transferir información directamente entre la imagen principal del usuario y el dispositivo en tamaños de bloque tan grandes como el que llama solicita sin utilizar almacenamientos intermedios. El método implica configurar un archivo especial de tipo carácter correspondiente al dispositivo en bruto y proporcionar subrutinas de lectura y escritura para crear una cabecera de almacenamiento intermedio privada no compartida con la información apropiada. Se pueden proporcionar subrutinas de apertura y cierre separadas, y se puede llamar a una subrutina de función especial para cinta magnética.

Interfaces de E/S de corriente

Las interfaces de E/S de corriente de datos proporcionan datos como una corriente de bytes que el sistema no interpreta, lo que ofrece una implementación más eficiente para los protocolos de red que el proceso de E/S de caracteres. No existen límites de registro al leer y escribir utilizando E/S de corriente. Por ejemplo, un proceso que lee 100 bytes de un conducto no puede determinar si el proceso que ha escrito los datos en el conducto ha realizado una sola grabación de 100 bytes, o dos grabaciones de 50 bytes, o incluso si los 100 bytes proceden de dos procesos diferentes.

Las E/S de secuencia pueden ser conexiones o FIFO (archivos de primera entrada y primera salida). Los FIFO son similares a los conductos porque permiten que los datos fluyan sólo en una dirección (de izquierda a derecha). Sin embargo, a un FIFO se le puede dar un nombre y se puede acceder a él mediante procesos no relacionados, a diferencia de un conducto. A veces se hace referencia a los FIFO como conductos con nombre. Puesto que tiene un nombre, se puede abrir un FIFO utilizando la subrutina fopen de E/S estándar. Para abrir un conducto, debe llamar a la subrutina pipe , que devuelve un descriptor de archivo, y a la subrutina fdopen de E/S estándar para asociar un descriptor de archivo abierto con una corriente de E/S estándar.

Nota: Las interfaces de E/S de corriente de datos almacenan datos en el almacenamiento intermedio a nivel de usuario y no pueden grabar los datos hasta que se realice la subrutina fclose o fflush , lo que puede dar lugar a resultados inesperados cuando se mezclan con E/S de archivo como, por ejemplo, read () o write ().

Se accede a las interfaces de E/S de corriente de datos a través de las siguientes subrutinas y macros:

cierre
Cierra una corriente
feof, ferror, clearerr o fileno
Comprobar el estado de una corriente
vaciado
Escribir todos los caracteres actualmente en almacenamiento intermedio de una corriente
fopen, freopen o fdopen
Abrir una ruta
fread o fwrite
Realizar entrada binaria
fseek, rewind, ftell, fgetpos o fsetpos
Volver a colocar el puntero de archivo de una ruta
getc, fgetc, getchar, o getw
Obtener un carácter o palabra de una corriente de entrada
gets o fgets
Obtener una serie de una secuencia
getwc, fgetwc o getwchar
Obtener un carácter ancho de una corriente de entrada
getws o fgetws
Obtener una serie de una secuencia
printf, fprintf, sprintf, wsprintf, vprintf, vfprintf, vsprintf, o vwsprintf
Imprimir salida formateada
putc, putchar, fputc o putw
Escribir un carácter o una palabra en una secuencia
puts o fputs
Escribir una serie en una secuencia
putwc, putwchar o fputwc
Escribir un carácter o una palabra en una secuencia
putws o fputws
Escribir una serie de caracteres ancha en una secuencia
scanf, fscanf, sscanf o wsscanf
Convertir entrada formateada
setbuf, setvbuf, setbuffer o setlinebuf
Asignar almacenamiento intermedio a una corriente
ungetc o ungetwc
Devolver un carácter a la corriente de entrada

Interfaces de E/S de terminal

Las interfaces de E/S de terminal operan entre un proceso y el kernel, proporcionando funciones tales como almacenamiento intermedio y salida formateada. Cada terminal y pseudoterminal tiene una estructura tty que contiene el ID de grupo de procesos actual. Este campo identifica el grupo de procesos para recibir las señales asociadas con la terminal. Se puede acceder a las interfaces de E/S de terminal a través del mandato iostat , que supervisa la carga de dispositivos del sistema de E/S, y el daemon uprintfd , que permite grabar mensajes de kernel en la consola del sistema.

Las características de terminal se pueden habilitar o inhabilitar mediante las subrutinas siguientes:

cfgetospeed, cfsetospeed, cfgetispeedo cfsetispeed
Obtener y establecer velocidades en baudios de entrada y salida
ioctl
Realiza funciones de control asociadas con el terminal
termdef
Características de terminal de consultas
tcdrenaje
Espera a que se complete la salida
flujo tct
Realiza funciones de control de flujo
tcflush
Descarta datos de la cola especificada
tcgetpgrp
Obtiene el ID de grupo de procesos en primer plano
tcsendbreak
Envía una interrupción en una línea de datos serie asíncrona
tcsetattr
Establece el estado de terminal
ttylock, ttywait, ttyunlocko ttylocked
Controlar funciones de bloqueo de tty
ttyname o isatty
Obtener el nombre de un terminal
ranura de tipo
Busca la ranura en el archivo utmp para el usuario actual

Interfaces de E/S asíncronas

Las subrutinas de E/S asíncronas permiten a un proceso iniciar una operación de E/S y hacer que la subrutina se devuelva inmediatamente después de que la operación se inicie o se coloque en cola. Se necesita otra subrutina para esperar a que se complete la operación (o devolver inmediatamente si la operación ya ha finalizado). Esto significa que un proceso puede solapar su ejecución con su E/S o solapar la E/S entre distintos dispositivos. Aunque la E/S asíncrona no mejora significativamente el rendimiento de un proceso que está leyendo un archivo de disco y grabando en otro archivo de disco, la E/S asíncrona puede proporcionar mejoras de rendimiento significativas para otros tipos de programas controlados por E/S, como por ejemplo programas que vuelcan un disco en una cinta magnética o muestran una imagen en una pantalla de imagen.

Aunque no es necesario, un proceso que está realizando E/S asíncrona puede indicar al kernel que lo notifique cuando un descriptor especificado esté preparado para E/S (también denominado E/S controlada por señal). Cuando se utiliza LEGACY AIO, el kernel notifica al usuario el proceso con la señal SIGIO. Cuando se utiliza POSIX AIO, el programador utiliza la estructura sigevent para determinar qué señal debe utilizar el kernel para notificar al proceso de usuario. Las señales incluyen SIGIO, SIGUSR1y SIGUSR2.

Para utilizar E/S asíncrona, un proceso debe realizar los pasos siguientes:

  1. Establezca un manejador para la señal SIGIO . Este paso sólo es necesario si se solicita la notificación mediante la señal.
  2. Establezca el ID de proceso o el ID de grupo de procesos para recibir las señales SIGIO . Este paso sólo es necesario si se solicita la notificación mediante la señal.
  3. Habilitar E/S asíncrona. El administrador del sistema normalmente determina si la E/S asíncrona está cargada (habilitada). La habilitación se produce durante el arranque del sistema.

Se proporcionan las siguientes subrutinas de E/S asíncronas:

aio_cancelar
Cancela una o más solicitudes de E/S asíncronas pendientes
aio_error
Recupera el estado de error de una solicitud de E/S asíncrona
aio_fsync
Sincroniza archivos asíncronos.
espera_aio
Suspende el proceso de llamada hasta que se haya completado un determinado número de solicitudes de E/S asíncronas.
aio_read
Lee de forma asíncrona desde un descriptor de archivo
aio_return
Recupera el estado de retorno de una solicitud de E/S asíncrona
aio_suspender
Suspende el proceso de llamada hasta que se hayan completado una o varias solicitudes de E/S asíncronas
aio_write
Escribe de forma asíncrona en un descriptor de archivo
lio_listio
Inicia una lista de solicitudes de E/S asíncronas con una sola llamada
poll o select
Comprobar el estado de E/S de varios descriptores de archivo y colas de mensajes

Para su uso con la subrutina poll , se proporcionan los siguientes archivos de cabecera:

poll.h
Define las estructuras y distintivos utilizados por la subrutina poll
aio.h
Define la estructura y los distintivos utilizados por las subrutinas aio_read, aio_writey aio_suspend