|
|
Tema 4. Manejo de Directorios y Ficheros
Especiales. |
1 ACCESO A DIRECTORIOSLos directorios son ficheros que le proporcionan al sistema una estructura jerárquica de árbol invertido. Los directorios se pueden abrir mediante una llamada open y pueden leerse mediante la llamada read, pero ningún usuario puede escribir en los directorios con llamadas a write. Para poder leer de un directorio es necesario conocer su estructura, pero la organización del mismo depende del sistema, para solucionar este problema existe una biblioteca estándar de funciones de manejo de directorios; y aunque no esta permitido modificar la estructura de un directorio, existen llamadas para crear, borrar ... directorios que actúan de manera indirecta sobre ellos. CREACION DE UN DIRECTORIO (mknod y mkdir)Para crear directorios en UNIX existen dos llamadas mknod y mkdir, aunque cada una de ellas actúa de una manera: Mknod: Crea un fichero nuevo.#include <sys/types.h> #include <sys/stat.h> int mknod (char *path, mode_t mode, int dev); Path: ruta donde se va a crear el nuevo directorio. Mode: especifica el modo del fichero. <sys/stat.h> : biblioteca la cual tiene definidas unas constantes. Dev: solo se utiliza cuando se va a crear un fichero de dispositivo. Esta llamada para la creación de un directorio solo puede ser usada por un usuario con privilegios de súper usuario, por lo tanto no es muy útil su utilización. Si se ejecuta debidamente, devuelve un valor 0, de lo contrario devolverá -1 y en errno estará el código del error producido. Mkdir: Otra llamada para la creación de un directorio.#include <sys/types.h> #include <sys/stat.h> int mkdir (char *path, mode_t mode); Path: ruta donde se va a crear el directorio. Mode: especifica el modo del fichero. Si se ejecuta debidamente, devuelve el valor 0, de lo contrario devolverá -1 y en errno estará el código del error producido. La diferencia respecto a la anterior llamada, es que mkdir puede escribirse a partir de mknod y cualquier usuario que tenga privilegios de súper usuario podrá ejecutarlo. BORRADO DE UN DIRECCTORIO (rmdir)La llamada que nos permite la eliminación de un directorio es rmdir. #include <unistd.h>int rmdir (char *path); Path: es el puntero que contiene la dirección del directorio que queremos borrar. Inconveniente: el directorio que deseamos borrar debe estar completamente vacío y no puede ser ningún directorio de trabajo de otro proceso. CREACIÓN DE NUEVAS ENTRADAS EN UN DIRECTORIO (link)En UNIX, en realidad los directorios se utilizan para asignar nombres de ficheros a un nodo-i, por lo tanto al poder haber varios nombres conectados al mismo nodo-i, se utiliza la llamada link, para poder enlazar un nombre con un nodo-i. #include <unistd.h>int link (char *path1, char *path2); Path1: contiene la ruta de un fichero ya existente. Path2: contiene el nombre del fichero, el cual se va enlazar con el nodo-i. Para deshacer un enlace que hayamos creados con anterioridad se utiliza la llamada unlink. #include <unistd.h>int unlink (char *path); Path: contiene la ruta del fichero que queremos eliminar. Si se ejecuta debidamente devuelve un 0, de lo contrario devolverá un -1. DIRECTORIOS ASOCIADOS A UN PROCESO (chdir y chroot)En UNIX existen multitud de directorios, por ejemplo el directorio raíz, directorio de trabajo actual, etc... por lo tanto para cambiar de uno a otro utilizamos la llamada chdir. #include <unistd.h>int chdir (char *path); Path: especifica la nueva dirección a la que queremos acceder. Dicha llamada devuelve un 0 si se ejecuta bien, y -1 si se produce algún error. La biblioteca estándar contiene una función que devuelve la ruta del directorio actual: #include <unistd.h>char *getcwd (char *buf, int size); Buf: es el puntero a la zona de memoria donde se guarda la ruta del directorio actual. Size: es el tamaño de buf. Si se ejecuta correctamente la llamada devolverá el mismo puntero que le pasamos por buf, de lo contrario devolverá NULL. Para cambiar el directorio raíz asociado a un proceso utilizamos la llamada chroot. #include <unistd.h>int chroot (char *path); Path: apunta a la cadena con la ruta del directorio, que actuara como nuevo directorio raíz. El inconveniente de esta llamada es que, hay que tener privilegios del súper usuario para su utilización. Si se ejecuta correctamente devuelve el valor 0, por lo contrario devuelve -1 y en errno coloca el código del error producido. BIBLIOTECA ESTÁNDAR DE ACCESO A DIRECTORIOSExisten ciertas llamadas especificas para leer el contenido de un directorio sin tener que preocuparse de la estructura del mismo. Son las siguientes: Opendir: Abre un directorio.#include <sys/types.h>#include <dirent.h> DIR *opendir (char *dirname); Dirname: contiene la ruta del fichero que queremos abrir. Opendir: devuelve un puntero a una estructura del tipo DIR. Al utilizar esta llamada para abrir un directorio necesitamos reservar un espacio en memoria para guardar el directorio que devuelve. Si se produce un error devolverá NULL y errno contendrá el código. Readdir: Lee las entradas de un directorio abierto ya.#include <sys/types.h>#include <dirent.h> struct dirent *readdir (DIR *dirp); Dirp: puntero al flujo del directorio ya abierto. Si se ejecuta correctamente actualiza el puntero a la siguiente entrada, de lo contrario, devolverá NULL cuando llegue al final o cuando se produzca un error. Al contrario de opendir esta llamada no necesita reserva en memoria. Closedir: Llamada para el cierre de un directorio.#include <sus/types.h>#include <dirent.h> int closedir (DIR *dirp); Dirp: puntero al flujo del directorio que queremos borrar. Esta llamada además de cerrar el fichero abierto se encarga a su vez de liberar el espacio en memoria reservado con anterioridad con la llamada a opendir. Si se realiza debidamente devolverá un 0, sino un -1. Seekdir, telldir y rewinddir:La primera función sitúa el puntero de lectura de un directorio, telldir devuelve la posición de ese puntero y rewinddir permite situar el puntero al principio del directorio y deja todo como quedo después de la llamada a opendir. #include <sys/types.h>#include <dirent.h> void seekdir (DIR *dirp, long loc); long telldir (DIR *dirp); void rewinddir (DIR *dirp); Dirp: puntero al flujo del directorio con el que vamos a trabajar. Loc: valor de la entrada donde posteriormente se situara el puntero de lectura. De estas tres funciones la única que devuelve algún valor es telldir, las otras dos nada, si se ejecuta correctamente devuelve la posición actual del puntero de lectura, de lo contrario devolverá -1. 2. ACCESO A FICHEROS ESPECIALESDentro de los ficheros especiales se engloban prácticamente todos los periféricos que hay conectados a un ordenador. Un acierto del sistema de UNIX es no darle trato especial a los periféricos y que puedan ser manipulados como cualquier otro fichero. Un dispositivo periférico es accesible a través de su fichero de dispositivo asociado (el cual se encuentra en el directorio /dev). Para leer o escribir datos en un periférico lo haremos de igual forma que con un fichero ordinario: abriremos con OPEN, leeremos datos con READ y escribiremos datos con WRITE. ENTRADA / SALIDA SOBRE TERMINALESLos terminales son dispositivos especiales que trabajan en modo carácter. Todo proceso que se ejecuta en UNIX tiene asociados 3 descriptores de fichero que le dan acceso a su terminal de control y son los 3 siguientes: 0 para la entrada estándar,1 para la salida estándar, y 2 para la salida estándar de errores. El fichero de dispositivo que permite a un proceso acceder a su terminal de control es /dev/tty. Con las llamadas siguientes reservaríamos manualmente nosotros los descriptores anteriores (si el sistema no los ha reservado él de forma automática): Close (0);Open ("/dev/tty", O_RDONLY); //Reserva del descriptor 0 Close (1); Open ("/dev/tty", O_RDONLY); //Reserva del descriptor 1 Close (2); Open ("/dev/tty", O_RDONLY); //Reserva del descriptor 2 En el sistema hay un terminal especial llamado consola-dispositivo /dev/console- que es utilizado para presentar los mensajes que se producen durante la puesta en marcha del sistema. Cada usuario que inicia una sesión de trabajo interactiva lo hace a través de un terminal, el cual tiene asociado un fichero de dispositivo que localmente se puede abrir como /dev/tty y que visto por otros usuarios tiene la forma /dev/tty##, donde ## equivale a dos dígitos. La orden WRITE es empleada para enviar mensajes a los usuarios que hay conectados al sistema. Su forma de uso es la siguiente: $ write usuariolínea de texto 1 línea de texto 2 ... línea de texto n ^D /Fin de fichero/ Esta secuencia hace que Usuario reciba en su terminal las n líneas de texto que le hemos enviado, pero para ello, antes tenemos que saber si el usuario existe y ha iniciado una sesión de trabajo y también tenemos que conocer cuál es el fichero de dispositivo que tiene asociado su terminal; para ello, hay que consultar el fichero /etc/utmp que es gestionado por el sistema y contiene información administrativa de los procesos que hay ejecutándose en un instante determinado. Bajate esta documentación en un archivo Acrobat Reader |