Departamento de Informática Taller de Sistemas Operativos Universidad Técnica Federico Santa María Entrada y Salida de Archivos 1 Departamento de Informática Universidad Técnica Federico Santa María Taller de Sistemas Operativos E/S Básica de Archivo • El servicio básico es sin buffering, a diferencias de la E/S estándar (stdio.h), dado que las primeras generan llamadas al sistema (read y write). • Son parte de POSIX.1, pero no de ANSI C • Funciones básicas: open, read, write, lseek y close. Raúl Monge II-2 Departamento de Informática Universidad Técnica Federico Santa María Taller de Sistemas Operativos Descriptor de Archivo • Para referenciar archivos abiertos en el núcleo. • Por convención, la shell asocia: – 0 – 1 – 2 Entrada estándar Salida estándar Error estándar • Número máximo de archivos abiertos está limitado (OPEN_MAX en POSIX.1) Raúl Monge II-3 1 Departamento de Informática Taller de Sistemas Operativos Universidad Técnica Federico Santa María Función: open #include <sys/types.h> #include <sys/stat.h> #include <sys/fcntl.h> int open(const char *pathname, int oflag, … /* , mode_t mode */ ); return: descriptor de archivo si OK, -1 si existe error • Permite abrir o crear un archivo • Tercer argumento sólo se usa cuando se crea un archivo. Raúl Monge II-4 Departamento de Informática Taller de Sistemas Operativos Universidad Técnica Federico Santa María Flag de Apertura • Se forma mediante OR de las opciones. • Se debe usar sólo una de las siguientes: O_RDONLY O_WRONLY O_RDWR Sólo para lectura Sólo para escritura Para lectura y escritura • Las siguientes opciones son opcionales (existen más): O_APPEND O_CREAT Agregar al final (atómicamente) Crear si no existe (tercer argumento especifica permiso de acceso) Genera error si archivo existe y se agregó O_CREAT Si archivo existe, lo trunca (con modo escritura) O_EXCL O_TRUNC Raúl Monge II-5 Departamento de Informática Universidad Técnica Federico Santa María Taller de Sistemas Operativos Función: creat #include <sys/types.h> #include <sys/stat.h> #include <sys/fcntl.h> int creat(const char *pathname , mode_t mode ); return: descriptor de archivo sólo para escritura si OK, -1 si existe error • Equivale a usar open con oflag: O_WRONLY | O_CREAT | O_TRUNC • Se requería en sistemas más antiguos. • Tiene la desventaja de que para leer es necesario cerrar y volver a abrir el archivo. Raúl Monge II-6 2 Departamento de Informática Universidad Técnica Federico Santa María Taller de Sistemas Operativos Función: close #include <unistd.h> int close(int filedes); return: 0 si OK, -1 si existe error • Al cerrar un archivo se liberan recursos (e.g. Locks) • Al terminar un proceso cierra automáticamente sus archivos abiertos. Raúl Monge II-7 Departamento de Informática Universidad Técnica Federico Santa María Taller de Sistemas Operativos Función: lseek #include <sys/types.h> #include <unistd.h> off_t lseek(int filedes, off_t offset, int whence); return: nuevo offset del archivo si OK, -1 si existe error • Permite posicionar el offset actual • Offset mide # de bytes desde comienzo del archivo • Operaciones de R/W empiezan desde offset actual y lo incrementan de acuerdo a lo efectivamente R/W • Archivo se abre por defecto con offset 0, salvo que se especifique opción O_APPEND. Raúl Monge II-8 Departamento de Informática Universidad Técnica Federico Santa María Taller de Sistemas Operativos Función: read #include <unistd.h> ssize_t read(int filedes, const void *buff, size_t nbytes); return: número de bytes leídos si OK, -1 si existe error • Devuelve número de bytes leídos, 0 si está en EOF. • Se incrementa posición actual antes del retorno • Existen varias razones porque no lee nbytes: – Se agotó el archivo – No existen más datos en el dispositivo (e.g. teclado) – El dispositivo tiene una estructura particular (e.g. lee registros) Raúl Monge II-9 3 Departamento de Informática Universidad Técnica Federico Santa María Taller de Sistemas Operativos Función: write #include <unistd.h> ssize_t write(int filedes, const void *buff, size_t nbytes); return: número de bytes escritos si OK, -1 si existe error • Valor de retorno es normalmente nbytes, sino ha ocurrido error (e.g. se lleno el disco) • Se actualiza posición actual antes del retorno • Si se ha especificado O_APPEND, posición actual se actualiza automáticamente al tamaño del archivo antes de escribir Raúl Monge II-10 Departamento de Informática Universidad Técnica Federico Santa María Taller de Sistemas Operativos Interpretación de whence (desde dónde) • Flags: SEEK_SET: desde el inicio SEEK_CUR: a partir de la posición actual SEEK_END: desde el final • Ejemplo: off_t curpos; curspos = lseek(fd, 0, SEEK_CUR); /* curspos tiene posición actual */ Raúl Monge II-11 Departamento de Informática Universidad Técnica Federico Santa María Taller de Sistemas Operativos Tamaño del Buffer • El tamaño del buffer tiene efecto sobre la eficiencia de la E/S. • Tamaño muy pequeño causa muchas llamadas al sistema (poca eficiencia en tiempo de CPU). • Existe un punto en que aumentar el tamaño no tiene efecto, pero obliga a usar más memoria. Raúl Monge II-12 4 Departamento de Informática Taller de Sistemas Operativos Universidad Técnica Federico Santa María Compartición de Archivos • Unix permite compartir archivos abiertos entre diferentes procesos. • Para manejar esta situación, se usan algunas estructuras de datos internas del núcleo: – Tabla de Descriptores (una por proceso) – Tabla de Archivos (una entrada por archivo abierto) – v-node (una por archivo activo; corresponde a un i-node en un archivo normal) Raúl Monge II-13 Departamento de Informática Taller de Sistemas Operativos Universidad Técnica Federico Santa María Estructuras de Control de Archivos Entrada en Tabla de Proceso flag ptr 0 1 2 Tabla de Archivos status offset ptr Tabla de v-nodes Activos info ptr Entrada en Tabla de Proceso flag ptr 0 1 2 Raúl Monge II-14 Departamento de Informática Universidad Técnica Federico Santa María Taller de Sistemas Operativos Operaciones Atómicas • Agregar datos a un archivo: posicionarse al final y luego escribir en una sola operación Solución: O_APPEND • Crear un archivo: Verificar si archivo existe, crearlo sino es el caso, en una sola operación. Solución: O_CREAT | O_EXCL Raúl Monge II-15 5 Departamento de Informática Taller de Sistemas Operativos Universidad Técnica Federico Santa María Funciones: dup y dup2 #include <unistd.h> int dup(int filedes); int dup2(int filedes1, int filedes1); return: nuevo descriptor de archivo si OK, -1 si existe error • • • • Permite duplicar un descriptor de archivo dup duplica en la primera entrada libre encontrada dup2 especifica con filedes2 hacia donde duplicar Es posible duplicar también con fcntl Raúl Monge II-16 Departamento de Informática Taller de Sistemas Operativos Universidad Técnica Federico Santa María Ejemplo de Duplicación Entrada en Tabla de Proceso Tabla de Archivos flag ptr 0 1 2 status offset ptr Tabla de v-nodes Activos info ptr Entrada en Tabla de Proceso Raúl Monge II-17 Departamento de Informática Universidad Técnica Federico Santa María Taller de Sistemas Operativos Función: fcntl #include <sys/types.h> #include <sys/unistat.h> #include <sys/fcntl.h> int fcntl(int fildes, int cmd, … /* , int arg */ ); return: depende de cmd si OK, -1 si existe error • Permite cambiar propiedades de un archivo ya abierto. • cmd especifica el tipo de orden y arg un argumento para la orden. Raúl Monge II-18 6 Departamento de Informática Universidad Técnica Federico Santa María Taller de Sistemas Operativos Comandos de fcntl • • • • • • • • • F_DUPFD : duplica un descriptor existente F_GETFD : obtiene flag del descriptor F_SETFD : modifica flag del descriptor F_GETFL : obtiene status de tabla de archivo F_SETFL : modifica status de tabla de archivo F_GETOWN : obtiene dueño de E/S asincrónica F_SETOWN : modifica dueño de E/S asincrónica F_GETLK : obtiene candados (locks) de registros F_SETLK : modifica candados (locks) de registros Raúl Monge II-19 Departamento de Informática Universidad Técnica Federico Santa María Taller de Sistemas Operativos Función: ioctl #include <sys/types.h> #include <sys/ioctl.h> int ioctl(int fildes, int request, …); return: no es parte de POSIX.1, y depende del dispositivo • Función comodín utilizada normalmente para el control de dispositivos Raúl Monge II-20 7