Llamadas al Sistema C para Operaciones con Ficheros en Linux/Unix

Enviado por Programa Chuletas y clasificado en Informática y Telecomunicaciones

Escrito el en español con un tamaño de 10,62 KB

Operaciones Fundamentales con Ficheros en C (Llamadas al Sistema)

int open(char *name, int flags, mode_t mode)

Abre un fichero especificado por name.

  • Devuelve un descriptor de fichero (fd) si tiene éxito, o -1 en caso de error.
  • flags: Determinan el modo de apertura:
    • O_WRONLY: Solo escritura.
    • O_RDONLY: Solo lectura.
    • O_RDWR: Lectura y escritura.
    • O_APPEND: Añadir al final del fichero en cada escritura.
    • O_CREAT: Crea el fichero si no existe (requiere el argumento mode).
    • O_TRUNC: Trunca el fichero a tamaño 0 si existe y se abre para escritura.
  • Si se crea el fichero (O_CREAT), mode especifica los permisos (afectados por umask).
  • Asigna el fd devuelto a una entrada en la tabla de descriptores de fichero del proceso (BCP), incrementa el contador de referencias del fichero (nrefs) y el contador de aperturas (nopens).

int creat(char *name, mode_t mode)

Crea y abre un fichero exclusivamente en modo escritura (O_WRONLY | O_CREAT | O_TRUNC).

  • Si el fichero no existe, lo crea vacío. El UID del fichero será el UID efectivo del proceso (UIDef), el GID será el GID efectivo (GIDef), y los permisos serán mode & ~umask.
  • Si el fichero ya existe, lo trunca a tamaño 0 sin alterar sus permisos originales.
  • Nota: La función open con las flags adecuadas es generalmente preferida sobre creat.

int close(int fd)

Cierra un descriptor de fichero, rompiendo la asociación entre fd y el fichero correspondiente.

  • Decrementa el contador de referencias (nrefs) de la entrada de la tabla de ficheros abiertos asociada.
  • Si nrefs llega a 0, se libera la entrada de la tabla y se decrementa el contador global de aperturas (nopens) del i-nodo.
  • Devuelve 0 si tiene éxito, o -1 en caso de error.

int dup(int fd)

Duplica un descriptor de fichero existente.

  • Crea y devuelve un nuevo descriptor de fichero (fd2) que comparte la misma entrada en la tabla de ficheros abiertos que fd.
  • Esto significa que fd y fd2 comparten el mismo fichero, el mismo puntero de lectura/escritura (PL/E) y el mismo modo de acceso.
  • Incrementa el contador de referencias (nrefs) de la entrada compartida.
  • El nuevo descriptor fd2 será el menor número entero no negativo disponible en la tabla de descriptores del proceso.
  • Devuelve el nuevo descriptor si tiene éxito, o -1 en caso de error.

int dup2(int oldfd, int newfd)

Duplica un descriptor de fichero en un descriptor específico.

  • Hace que newfd se refiera a la misma entrada de la tabla de ficheros abiertos que oldfd.
  • Si newfd ya estaba abierto, se cierra implícitamente antes de la duplicación (de forma atómica).
  • Si oldfd y newfd son iguales, dup2 no hace nada y devuelve newfd.
  • Equivalente conceptualmente a close(newfd); seguido de una asignación similar a dup(oldfd), pero garantizando que newfd sea el descriptor resultante.
  • Devuelve newfd si tiene éxito, o -1 en caso de error.
  • Ejemplo: dup2(fd, 1) redirige la salida estándar (descriptor 1) al fichero asociado con fd.

ssize_t read(int fd, void *buf, size_t n_bytes)

Lee datos de un fichero.

  • Intenta leer hasta n_bytes del fichero asociado a fd y los almacena en el buffer apuntado por buf.
  • Devuelve el número de bytes realmente leídos (puede ser menor que n_bytes si se alcanza el final del fichero o si hay interrupciones).
  • Devuelve 0 si se alcanza el final del fichero (EOF).
  • Devuelve -1 en caso de error.
  • Incrementa la posición del puntero de lectura/escritura (PL/E) según el número de bytes leídos.

ssize_t write(int fd, void *buf, size_t nbytes)

Escribe datos en un fichero.

  • Escribe hasta nbytes desde el buffer apuntado por buf en el fichero asociado a fd.
  • Devuelve el número de bytes realmente escritos (puede ser menor que nbytes si ocurre un error o interrupción).
  • Devuelve -1 en caso de error.
  • Incrementa la posición del puntero de lectura/escritura (PL/E) según el número de bytes escritos.
  • Puede aumentar el tamaño del fichero si la escritura se realiza más allá del final actual.

off_t lseek(int fd, off_t offset, int whence)

Modifica la posición del puntero de lectura/escritura (PL/E) del fichero asociado a fd.

  • Devuelve la nueva posición del puntero (medida en bytes desde el inicio del fichero) si tiene éxito, o -1 en caso de error.
  • El cálculo de la nueva posición depende de whence:
    • SEEK_SET: La nueva posición es offset bytes desde el inicio del fichero.
    • SEEK_CUR: La nueva posición es la posición actual más offset bytes.
    • SEEK_END: La nueva posición es el tamaño actual del fichero más offset bytes.
  • lseek por sí solo no aumenta el tamaño del fichero. Sin embargo, si se posiciona el puntero más allá del final actual y luego se realiza una escritura, el espacio intermedio se rellena con bytes nulos (\0).
  • Ejemplos útiles:
    • Obtener tamaño del fichero: tam = lseek(fd, 0, SEEK_END);
    • Obtener posición actual: pos_act = lseek(fd, 0, SEEK_CUR);
    • Volver al inicio: lseek(fd, 0, SEEK_SET);

int link(char *existing, char *new)

Crea un nuevo enlace físico (hard link) llamado new que apunta al mismo i-nodo que el fichero existing.

  • Incrementa el contador de enlaces del i-nodo.
  • Requiere permisos de escritura en el directorio donde se creará new.
  • new no debe existir previamente.
  • existing y new son indistinguibles a nivel de fichero; comparten los mismos datos y metadatos (excepto el nombre y la ruta).
  • Devuelve 0 si tiene éxito, o -1 en caso de error.

int symlink(char *existing, char *new)

Crea un enlace simbólico (symbolic link o soft link) llamado new que apunta a la ruta existing.

  • new es un fichero especial que contiene la ruta de existing.
  • Requiere permisos de escritura en el directorio donde se creará new.
  • new no debe existir previamente.
  • Cuando se accede a new, el sistema operativo generalmente sigue la ruta almacenada para acceder a existing.
  • Los permisos se comprueban tanto para el enlace simbólico como para el fichero/directorio apuntado (existing) y todos los componentes de su ruta.
  • Si existing es eliminado o renombrado, el enlace new queda "roto" o "abandonado" (dangling link).
  • Devuelve 0 si tiene éxito, o -1 en caso de error.

int unlink(char *pathname)

Elimina un nombre (enlace) del sistema de ficheros.

  • Borra la entrada pathname del directorio que la contiene.
  • Decrementa el contador de enlaces del i-nodo asociado a pathname.
  • Requiere permisos de escritura en el directorio padre de pathname.
  • Si el enlace eliminado era el último enlace físico al fichero y ningún proceso tiene el fichero abierto, el espacio ocupado por los datos del fichero y su i-nodo se marcan como libres (el fichero se borra efectivamente).
  • Si era el último enlace físico pero algún proceso aún tiene el fichero abierto, el fichero permanecerá accesible para esos procesos y sus datos e i-nodo no se liberarán hasta que el último proceso cierre su descriptor de fichero asociado.
  • Si pathname era un enlace simbólico, simplemente se elimina el propio enlace simbólico sin afectar al fichero o directorio al que apuntaba.
  • Devuelve 0 si tiene éxito, o -1 en caso de error.

int pipe(int fd[2])

Crea una tubería (pipe), un mecanismo de comunicación unidireccional entre procesos.

  • Crea un par de descriptores de fichero conectados, que apuntan a un buffer interno gestionado por el kernel (asociado a un i-nodo de tipo tubería).
  • Los descriptores se devuelven en el array fd:
    • fd[0]: Extremo de lectura de la tubería.
    • fd[1]: Extremo de escritura de la tubería.
  • Devuelve 0 si tiene éxito, o -1 en caso de error.
  • Comportamiento de read sobre fd[0]:
    • Si la tubería está vacía y hay algún proceso que tiene abierto fd[1], la llamada a read se bloquea hasta que se escriban datos.
    • Si la tubería está vacía y todos los descriptores de escritura (fd[1]) han sido cerrados, read devuelve 0 (EOF).
  • Comportamiento de write sobre fd[1]:
    • Si la tubería está llena (ha alcanzado su capacidad máxima) y hay algún proceso que tiene abierto fd[0], la llamada a write se bloquea hasta que se lea espacio.
    • Si la tubería está llena o no, pero todos los descriptores de lectura (fd[0]) han sido cerrados, el proceso escritor recibe la señal SIGPIPE (que por defecto termina el proceso).
  • Importante: Los procesos que usan la tubería (generalmente padre e hijo después de un fork) deben cerrar los extremos de la tubería que no utilizan para evitar bloqueos indefinidos o condiciones de EOF incorrectas.

Entradas relacionadas: