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 argumentomode
).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 porumask
). - 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ánmode & ~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 sobrecreat
.
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 quefd
. - Esto significa que
fd
yfd2
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 queoldfd
. - Si
newfd
ya estaba abierto, se cierra implícitamente antes de la duplicación (de forma atómica). - Si
oldfd
ynewfd
son iguales,dup2
no hace nada y devuelvenewfd
. - Equivalente conceptualmente a
close(newfd);
seguido de una asignación similar adup(oldfd)
, pero garantizando quenewfd
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 confd
.
ssize_t read(int fd, void *buf, size_t n_bytes)
Lee datos de un fichero.
- Intenta leer hasta
n_bytes
del fichero asociado afd
y los almacena en el buffer apuntado porbuf
. - 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 porbuf
en el fichero asociado afd
. - 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 esoffset
bytes desde el inicio del fichero.SEEK_CUR
: La nueva posición es la posición actual másoffset
bytes.SEEK_END
: La nueva posición es el tamaño actual del fichero másoffset
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);
- Obtener tamaño del fichero:
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
ynew
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 deexisting
.- 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 aexisting
. - 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 enlacenew
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
sobrefd[0]
:- Si la tubería está vacía y hay algún proceso que tiene abierto
fd[1]
, la llamada aread
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).
- Si la tubería está vacía y hay algún proceso que tiene abierto
- Comportamiento de
write
sobrefd[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 awrite
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ñalSIGPIPE
(que por defecto termina el proceso).
- Si la tubería está llena (ha alcanzado su capacidad máxima) y hay algún proceso que tiene abierto
- 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.