FCNTL(2) Manual del Programador de Linux FCNTL(2)
fcntl - manipula el descriptor de fichero
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
fcntl realiza una de las diversas y variadas operaciones que se pueden
hacer sobre fd. La operacin en cuestin se determina mediante cmd.
Tratamiento de la bandera cerrar al ejecutar
F_DUPFD
Busca el descriptor de fichero disponible de menor nmero, mayor
o igual que arg, y lo convierte en una copia de fd. Esto es
diferente en dup2(2) que usa exactamente el descriptor especifi-
cado.
Los descriptores antiguo y nuevo pueden usarse indistintamente.
Ambos comparten bloqueos (``locks''), indicadores de posicin de
ficheros y opciones o banderas (``flags''); por ejemplo, si la
posicin del fichero se modifica usando lseek en uno de los
descriptores, la posicin del otro resulta modificada simultnea-
mente.
Sin embargo, los dos descriptores no comparten la bandera close-
on-exec (cerrar al ejecutar). La bandera close-on-exec de la
copia est desactivada, lo que significa que no se cerrar al eje-
cutar.
En caso de xito, se devuelve el nuevo descriptor.
F_GETFD
Lee la bandera close-on-exec. Si el bit FD_CLOEXEC es 0, el
fichero permanecer abierto tras exec, en caso contrario se cer-
rar el fichero.
F_SETFD
Establece la bandera close-on-exec al valor especificado por el
bit FD_CLOEXEC de arg.
Banderas de situacin de un fichero
Un descriptor de fichero posee ciertas banderas asociadas, inicial-
izadas por open(2) y posiblemente modificadas por fcntl(2). Las ban-
deras se comparten entre copias (hechas con dup(2), fork(2), etc.) del
mismo descriptor de fichero.
Las banderas y su semntica estn descritas en open(2).
F_GETFL
Lee las banderas de un descriptor de fichero.
F_SETFL
De las banderas de un descriptor, establece la parte que se cor-
responde con las banderas de situacin de un fichero al valor
especificado por arg. Los restantes bits (modo de acceso, ban-
deras de creacin de un fichero) de arg se ignoran. En Linux,
esta orden slo puede cambiar las banderas O_APPEND, O_NONBLOCK,
O_ASYNC y O_DIRECT.
Bloqueos (candados) consultivos
F_GETLK, F_SETLK y F_SETLKW se usan para adquirir, liberar y comprobar
la existencia de bloqueos de registros (tambin conocidos como bloqueos
de segmentos de ficheros o regiones de ficheros). El tercer argumento
lock es un puntero a una estructura que tiene, al menos, los siguientes
campos (en un orden indeterminado).
struct flock {
...
short l_type; /* Tipo de bloqueo: F_RDLCK,
F_WRLCK, F_UNLCK */
short l_whence; /* Cmo interpretar l_start:
SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* Direccin de inicio del bloqueo */
off_t l_len; /* Nmero de bytes a bloquear */
pid_t l_pid; /* PID del proceso que bloquea nuestro candado
(slo F_GETLK) */
...
};
Los campos l_whence, l_start y l_len de esta estructura especifican el
rango de bytes que deseamos bloquear. l_start es la direccin inicial
para el bloqueo y se interpreta relativa a: el inicio del fichero (si
l_whence es SEEK_SET); la posicin actual dentro del fichero (si
l_whence es SEEK_CUR) o el fin del fichero (si l_whence es SEEK_END).
En los dos ltimos casos, l_start puede ser un nmero negativo siempre
que la direccin inicial final no quede antes del principio del fichero.
l_len es un entero no negativo (aunque vea NOTAS ms abajo) que indica
el nmero de bytes a bloquear. Los bytes que se encuentren ms all del
final del fichero se pueden bloquear, pero no los bytes que se encuen-
tren antes del inicio del fichero. El especificar 0 para l_len tiene un
significado especial: bloquear todos los bytes desde la posicin indi-
cada por l_whence y l_start hasta el final del fichero, sin importar
cunto crezca el fichero.
El campo l_type se puede usar para colocar un bloqueo de lectura
(F_RDLCK) o de escritura (F_WDLCK) sobre un fichero. Varios procesos
pueden tener un bloqueo de lectura (bloqueo compartido) sobre una regin
de fichero, pero slo un proceso puede tener un bloqueo de escritura
(bloqueo exclusivo). Un bloqueo exclusivo excluye a todos los dems blo-
queos, tanto compartidos como exclusivos. Un nico proceso slo puede
tener un tipo de bloqueo sobre una regin de fichero; si se aplica un
nuevo bloqueo a una regin ya bloqueada, el bloqueo existente se con-
vierte al nuevo tipo de bloqueo. (Tales conversiones pueden suponer
dividir, reducir o fusionar un bloqueo existente si el rango de bytes
especificado por el nuevo bloqueo no coincide exactamente con el rango
del bloqueo existente).
F_SETLK
Adquiere un bloqueo (cuando l_type es F_RDLCK o F_WRLCK) o lib-
era un bloqueo (cunado l_type es F_UNLCK) sobre los bytes
especificados por los campos l_whence, l_start y l_len de lock.
Si otro proceso mantiene ya un bloqueo que entra en conflicto
con el nuevo, la llamada devuelve -1 y asigna a errno el cdigo
de error EACCES o EAGAIN.
F_SETLKW
Como F_SETLK, pero si ya hay un bloqueo sobre el fichero que
entra en conflicto con el nuevo, entonces espera a que el blo-
queo se libere. Si llega y se captura una seal mientras se est
esperando, se interrumpe la llamada y (tras terminar el mane-
jador de seal) regresa inmediatamente (devolviendo -1 y asignado
a errno el valor EINTR).
F_GETLK
Al entrar a esta llamada, lock describe un bloqueo que nos gus-
tara colocar en un fichero. Si el bloqueo se pudiera colocar,
fcntl() realmente no lo colocar, pero devolver F_UNLCK en el
campo l_type de lock y dejar los otros campos de la estructura
sin cambiar. Si uno o ms bloqueos incompatibles impidieran que
este bloqueo se colocara, entonces fcntl() devolver detalles
sobre uno de estos bloqueos en los campos l_type, l_whence,
l_start y l_len de lock y asignar a l_pid el PID del proceso que
posee el bloqueo.
Para colocar un bloqueo de lectura, se debe abrir fd para lectura. Para
colocar un bloqueo de escritura, se debe abrir fd para escritura. Para
colocar ambos tipos de bloqueo, abra un fichero para lectura y escrit-
ura.
Adems de ser eliminados por un F_UNLCK explcito, los bloqueos de reg-
istros se liberan automticamente cuando un proceso termina o cierra
cualquier descriptor de fichero que haga referencia a un fichero sobre
el que se mantienen los bloqueos. Esto est mal: significa que un pro-
ceso puede perder los bloqueos sobre un fichero como /etc/passwd o
/etc/mtab cuando, por alguna razn, una funcin de biblioteca decida
abrir, leer y cerrar el fichero.
Los bloqueos de registros no los hereda un hijo creado mediante
fork(2), pero se conservan a travs de execve(2).
Debido al almacenamiento temporal que realiza stdio(3), se debera evi-
tar el bloqueo de registros con rutinas de esa biblioteca; en su lugar,
use read(2) y write(2).
Bloqueos obligatorios
(No POSIX.) Los bloqueos de registro anteriores pueden ser o bien con-
sultivos o bien obligatorios, y son consultivos por omisin. Para usar
bloqueos obligatorios, se debe habilitar dicho tipo de bloqueo en el
sistema de ficheros que contiene el fichero a bloquear (usando la opcin
"-o mand" en mount(8)) y en el propio fichero (deshabilitando el per-
miso de ejecucin para el grupo y activado el bit de permiso set-GID).
Los bloqueos consultivos no son de obligado cumplimiento y slo son
tiles entre procesos que cooperan. Los bloqueos obligatorios son
respetados por todos los procesos.
Manejo de seales
F_GETOWN, F_SETOWN, F_GETSIG y F_SETSIG se utilizan para gestionar las
seales de disponibilidad de E/S:
F_GETOWN
Obtiene el ID de proceso o el grupo de procesos que actualmente
recibe las seales SIGIO y SIGURG para los eventos sobre el
descriptor de fichero fd.
Los grupos de procesos se devuelven como valores negativos.
F_SETOWN
Establece el ID de proceso o el grupo de procesos que recibir
las seales SIGIO y SIGURG para los eventos sobre el descriptor
de fichero fd.
Los grupos de procesos se especifican mediante valores nega-
tivos. (Se puede usar F_SETSIG para especificar una seal difer-
ente a SIGIO).
Si activa la bandera de estado O_ASYNC sobre un descriptor de
fichero (tanto si proporciona esta bandera con la llamada
open(2) como si usa la orden F_SETFL de fcntl), se enviar una
seal SIGIO cuando sea posible la entrada o la salida sobre ese
descriptor de fichero.
El proceso o el grupo de procesos que recibir la seal se puede
seleccionar usando la orden F_SETOWN de la funcin fcntl. Si el
descriptor de fichero es un conector (``socket''), esto tambin
seleccionar al recipiente de las seales SIGURG que se entregan
cuando llegan datos fuera de orden (``out-of-band'', OOB) sobre
el enchufe. (SIGURG se enva en cualquier situacin en la que
select(2) informara que el conector tiene una "condicin excep-
cional"). Si el descriptor de fichero corresponde a un disposi-
tivo de terminal, entonces las seales SIGIO se envan al grupo de
procesos en primer plano de la terminal.
F_GETSIG
Obtiene la seal enviada cuando la entrada o la salida son posi-
bles. Un valor cero significa que se enva SIGIO. Cualquier otro
valor (incluyendo SIGIO) es la seal enviada en su lugar y en
este caso se dispone de informacin adicional para el manejador
de seal si ste se instala con SA_SIGINFO.
F_SETSIG
Establece la seal enviada cuando la entrada o la salida son
posibles. Un valor cero significa enviar la seal por defecto
SIGIO. Cualquier otro valor (incluyendo SIGIO) es la seal a
enviar en su lugar y en este caso se dispone de informacin adi-
ciona para el manejador de seal si ste se instala con SA_SIG-
INFO.
Usando F_SETSIF con un valor distinto de cero y asignando
SA_SIGINFO para el manejador de seal (vea sigaction(2)), se pasa
informacin extra sobre los eventos de E/S al manejador en la
estructura siginfo_t. Si el campo si_code indica que la fuente
es SI_SIGIO, el campo si_fd proporciona el descriptor de fichero
asociado con el evento. En caso contrario, no se indican qu
descriptores de ficheros hay pendientes y, para determinar qu
descriptores de fichero estn disponibles para E/S, debera usar
los mecanismos usuales (select(2), poll(2), read(2) con O_NON-
BLOCK activo, etc.).
Seleccionando una seal de tiempo real POSIX.1b (valor >= SIGRT-
MIN), se pueden encolar varios eventos de E/S usando los mismos
nmeros de seal. (El encolamiento depende de la memoria
disponible). Se dispone de informacin extra si se asigna SA_SIG-
INFO al manejador de seal, como antes.
Usando estos mecanismos, un programa puede implementar E/S totalmente
asncrona, sin usar select(2) ni poll(2) la mayor parte del tiempo.
El uso de O_ASYNC, F_GETOWN y F_SETOWN es especfico de Linux y BSD.
F_GETSIG y F_SETSIG son especficos de Linux. POSIX posee E/S asncrona y
la estructura aio_sigevent para conseguir cosas similares; stas tambin
estn disponibles en Linux como parte de la biblioteca de C de GNU (GNU
C Library, Glibc).
Arrendamientos
F_SETLEASE y F_GETLEASE (Linux 2.4 y posteriores) se usan (respectiva-
mente) para establecer y obtener la configuracin actual del arren-
damiento del proceso invocador sobre el fichero referenciado por fd.
Un arrendamiento de fichero proporciona un mecanismo por medio del cual
al proceso que posee el arrendamiento (el "arrendatario") se le noti-
fica (mediante el envo de una seal) cundo otro proceso (el
"competidor") intenta abrir (open(2)) o truncar (truncate(2)) ese
fichero.
F_SETLEASE
Establece o elimina un arrendamiento de fichero segn qu valor de
los siguientes se especifique en el entero arg:
F_RDLCK
Obtiene un arrendamiento de lectura. Esto har que se nos
informe cuando otro proceso abra el fichero para escribir
en l o cuando lo trunque.
F_WRLCK
Obtiene un arrendamiento de escritura. Esto har que se
nos informe cuando otro proceso abra el fichero (para
leer o escribir) o lo trunque. Slo se puede colocar un
arrendamiento de escritura en un fichero cuando ningn
otro proceso lo tenga abierto en ese momento.
F_UNLCK
Elimina nuestro arrendamiento del fichero.
Un proceso slo puede tener un tipo de arrendamiento sobre un fichero.
Los arrendamientos slo se pueden obtener para ficheros regulares. Un
proceso normal slo puede obtener un arrendamiento sobre un fichero cuyo
UID coincida con el UID de sistema de ficheros del proceso.
F_GETLEASE
Indica qu tipo de arrendamiento tenemos sobre el fichero refer-
enciado por fd devolviendo F_RDLCK, F_WRLCK o F_UNLCK, lo que
indica, respectivamente, que el proceso invocador posee un
arrendamiento de lectura, de escritura o que no posee arren-
damiento alguno sobre el fichero. (El tercer argumento de
fcntl() se omite.)
Cuando el competidor realiza un open() o truncate() que entra en con-
flicto con un arrendamiento establecido mediante F_SETLEASE, el ncleo
bloquea la llamada al sistema (a menos que se especifique la opcin
O_NONBLOCK en open(), en cuyo caso la llamada regresa inmediatamente
con el error EWOULDBLOCK). El ncleo entonces notifica al arrendatario
envindole una seal (SIGIO por omisin). El arrendatario debe responder
a la recepcin de esta seal haciendo cualquier limpieza que sea nece-
saria para preparar el fichero para que sea accedido por otro proceso
(por ejemplo, vaciando los buffers en cach) y entonces eliminar su
arrendamiento ejecuntado una orden F_SETLEASE que especifique en arg el
valor F_UNLCK.
Si el arrendatario no libera el arrendamiento antes del nmero de segun-
dos especificado en /proc/sys/fs/lease-break-time y la llamada al sis-
tema del competidor sigue bloqueada (es decir, el competidor no espe-
cific O_NONBLOCK en su llamada open() y la llamada al sistema no ha
sido interrumpida por un manejador de seal), entonces el ncleo pone fin
al arrendamiento del arrendatario por la fuerza.
Una vez que se ha eliminado voluntariamente o por la fuerza el arren-
damiento, y suponiendo que el competidor no ha desbloqueado su llamada
al sistema, el ncleo permite continuar a la llamada al sistema del com-
petidor.
La seal por omisin que se usa para informar al arrendatario es SIGIO,
pero se puede cambiar usando la orden F_SETSIG de fcntl (). Si se eje-
cuta una orden F_SETSIG (incluso una que especifique SIGIO) y el mane-
jador de seal se establece usando SA_SIGINFO, el manejador recibir una
estructura siginfo_t como su segundo argumento y el campo si_fd de este
argumento contendr el descriptor del fichero arrendado que ha sido
accedido por otro proceso. (Esto es til si el invocador tiene arren-
damientos para varios ficheros).
Notificacin de cambios en ficheros y directorios
F_NOTIFY
(Linux 2.4 y posteriores) Produce una notificacin cuando cambia
el directorio referenciado por fd o cualquiera de los ficheros
que contiene. Los eventos a notificar se indican en arg, que es
una mscara de bits que se especifica mediante un O-lgico de cero
o ms de los siguientes bits:
Bit Descripcin (evento en el directorio)
---------------------------------------------------------------------
DN_ACCESS Se ha accedido a un fichero (read, pread, readv)
DN_MODIFY Se ha modificado un fichero (write, pwrite,
writev, truncate, ftruncate)
DN_CREATE Se ha creado un fichero (open, creat, mknod,
mkdir, link, symlink, rename)
DN_DELETE Se ha borrando un fichero (unlink, rename a
otro directorio, rmdir)
DN_RENAME Se ha cambiado el nombre de un fichero de este
directorio (rename)
DN_ATTRIB Se han cambiado los atributos de un fichero
(chown, chmod, utime[s])
(Para obtener estas definiciones, se debe define la macro
_GNU_SOURCE antes de incluir <fcntl.h>.)
Las notificaciones de directorio normalmente se reciben una nica
vez (son de tipo ``one-shot'') y la aplicacin debe volver a
hacer el registro para recibir notificaciones adicionales. Otra
posibilidad es incluir DN_MULTISHOT en arg, en cuyo caso la
notificacin se producir hasta que se elimine explcitamente. Una
serie de llamadas que especifican DN_MULTISHOT es acumulativa,
con los eventos en arg aadindose al conjunto ya monitorizado.
Para desactivar la notificacin de todos los eventos, haga una
llamada F_NOTIFY especificando 0 en arg.
La notificacin se produce mediante el envo de una seal. La seal
por omisin es SIGIO, pero se puede cambiar usando la orden
F_SETSIG de fcntl(). En el segundo caso, el manejador de seal
recibe una estructura siginfo_t como su segundo argumento (si el
manejador se estableci usando SA_SIGINFO) y el campo si_fd de
esta estructura contiene el descriptor de fichero que produjo la
notificacin (til cuando se establecen notificaciones en varios
directorios).
Especialmente cuando se usa DN_MULTISHOT, se debera usar una
seal POSIX.1b de tiempo real para notificacin, de tal manera que
se pueden encolar multiples notificaciones.
Para una llamada con xito, el valor devuelto depende de la operacin:
F_DUPFD El nuevo descriptor.
F_GETFD Valor de la bandera.
F_GETFL Valor de las banderas.
F_GETOWN Valor del propietario del descriptor.
F_GETSIG Valor de la seal enviada cuando la lectura o la escritura son
posibles o cero para el comportamiento tradicional con SIGIO.
Para cualquier otra orden
Cero.
En caso de error el valor devuelto es -1 y se asigna a errno un valor
apropiado.
EACCESS o EAGAIN
Se ha prohibido la operacin debido a bloqueos mantenidos por
otros procesos. O se ha prohibido la operacin porque el fichero
ha sido proyectado (``mapped'') en memoria por otro proceso.
EDEADLK
Se ha detectado que la orden F_SETLKW especificada provocara un
interbloqueo.
EFAULT lock est fuera de su espacio de direcciones accesible.
EBADF fd no es un descriptor de fichero abierto o la orden era F_SETLK
o F_SETLKW y el modo de apertura del descriptor de fichero no
coincide con el tipo de bloqueo solicitado.
EINTR Para F_SETLKW, la orden ha sido interrumpida por una seal. Para
F_GETLK y F_SETLK, la orden ha sido interrumpida por una seal
antes de que el bloqueo se haya comprobado o adquirido. Esto
ocurre con ms probabilidad al poner un bloqueo en un fichero
remoto (por ejemplo, un bloqueo sobre NFS) pero algunas veces
puede ocurrir localmente.
EINVAL Para F_DUPFD, arg es negativo o mayor que el valor mximo permi-
tido. Para F_SETSIG, arg no es un nmero de seal permitido.
EMFILE Para F_DUPFD, el proceso ya ha llegado al nmero mximo de
descriptores de ficheros abiertos.
ENOLCK Demasiados bloqueos de segmentos abiertos, la tabla de bloqueos
est llena o ha fallado un protocolo de bloqueos remoto (por
ejemplo, un bloqueo sobre NFS).
EPERM Se ha intentado quitar la bandera O_APPEND sobre un fichero que
tiene activo el atributo de ``slo aadir'' (append-only).
Los errores devueltos por dup2 son distintos de aqullos dados por
F_DUPFD.
Desde el ncleo 2.0, no hay interaccin entre los tipos de bloqueo colo-
cados por flock(2) y fcntl(2).
POSIX 1003.1-2001 permite que l_len sea negativo. (Y si lo es, el
intervalo descrito por el bloqueo cubre los bytes desde l_start+l_len
hasta l_start-1 inclusive.) Sin embargo, para los ncleos actuales, la
llamada al sistema de Linux devuelve EINVAL en esta situacin.
Otros sistemas tienen ms campos en struct flock como, por ejemplo,
l_sysid. Evidentemente, l_pid slo no va a ser muy til si el proceso
que posee el bloqueo puede residir en una mquina diferente.
SVID, AT&T, POSIX, X/OPEN, BSD 4.3. Slo las operaciones F_DUPFD,
F_GETFD, F_SETFD, F_GETFL, F_SETFL, F_GETLK, F_SETLK y F_SETLKW se
especifican en POSIX.1. F_GETOWN y F_SETOWN son BSD-ismos no aceptados
en SVr4; F_GETSIG y F_SETSIG son especficos de Linux. F_NOTIFY,
F_GETLEASE y F_SETLEASE son especficos de Linux. (Defina la macro
_GNU_SOURCE antes de incluir <fcntl.h> para obtener estas defini-
ciones.) Las banderas legales para F_GETFL/F_SETFL son aqullas que
acepta open(2) y varan entre estos sistemas; O_APPEND, O_NONBLOCK,
O_RDONLY y O_RDWR son las que se mencionan en POSIX.1. SVr4 admite
algunas otras opciones y banderas no documentadas aqu.
SVr4 documenta las condiciones de error adicionales EIO, ENOLINK y
EOVERFLOW.
dup2(2), flock(2), lockf(3), open(2), socket(2)
Vea tambin locks.txt, mandatory.txt y dnotify.txt en
/usr/src/linux/Documentation.
Linux-2.5.18 24-04-2002 FCNTL(2)