fcntl

FCNTL(2)                 Manual del Programador de Linux                FCNTL(2)



NOMBRE
       fcntl - manipula el descriptor de fichero

SINOPSIS
       #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);

DESCRIPCIÓN
       fcntl realiza una de las diversas y variadas operaciones que se pueden
       hacer sobre fd.  La operación en cuestión se determina mediante cmd.

   Tratamiento de la bandera «cerrar al ejecutar»
       F_DUPFD
              Busca el descriptor de fichero disponible de menor número, mayor o
              igual que arg, y lo convierte en una copia de fd.  Esto es
              diferente en dup2(2) que usa exactamente el descriptor
              especificado.

              Los descriptores antiguo y nuevo pueden usarse indistintamente.
              Ambos comparten bloqueos (``locks''), indicadores de posición de
              ficheros y opciones o banderas (``flags''); por ejemplo, si la
              posición del fichero se modifica usando lseek en uno de los
              descriptores, la posición del otro resulta modificada
              simultáneamente.

              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
              ejecutar.

              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
              cerrará el fichero.

       F_SETFD
              Establece la bandera close-on-exec al valor especificado por el
              bit FD_CLOEXEC de arg.

   Banderas de situación de un fichero
       Un descriptor de fichero posee ciertas banderas asociadas, inicializadas
       por open(2) y posiblemente modificadas por fcntl(2).  Las banderas se
       comparten entre copias (hechas con dup(2), fork(2), etc.) del mismo
       descriptor de fichero.

       Las banderas y su semántica están 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
              corresponde con las banderas de situación de un fichero al valor
              especificado por arg.  Los restantes bits (modo de acceso,
              banderas de creación de un fichero) de arg se ignoran.  En Linux,
              esta orden sólo 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 (también 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;  /* Cómo interpretar l_start:
                                 SEEK_SET, SEEK_CUR, SEEK_END */
             off_t l_start;   /* Dirección de inicio del bloqueo */
             off_t l_len;     /* Número de bytes a bloquear */
             pid_t l_pid;     /* PID del proceso que bloquea nuestro candado
                                 (sólo 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 dirección inicial
       para el bloqueo y se interpreta relativa a: el inicio del fichero (si
       l_whence es SEEK_SET); la posición 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 número negativo siempre que la
       dirección inicial final no quede antes del principio del fichero.  l_len
       es un entero no negativo (aunque vea NOTAS más abajo) que indica el
       número de bytes a bloquear. Los bytes que se encuentren más allá del
       final del fichero se pueden bloquear, pero no los bytes que se encuentren
       antes del inicio del fichero. El especificar 0 para l_len tiene un
       significado especial: bloquear todos los bytes desde la posición indicada
       por l_whence y l_start hasta el final del fichero, sin importar cuánto
       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 región
       de fichero, pero sólo un proceso puede tener un bloqueo de escritura
       (bloqueo exclusivo). Un bloqueo exclusivo excluye a todos los demás
       bloqueos, tanto compartidos como exclusivos. Un único proceso sólo puede
       tener un tipo de bloqueo sobre una región de fichero; si se aplica un
       nuevo bloqueo a una región ya bloqueada, el bloqueo existente se
       convierte 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 libera
              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 código 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 bloqueo se
              libere. Si llega y se captura una señal mientras se está
              esperando, se interrumpe la llamada y (tras terminar el manejador
              de señal) regresa inmediatamente (devolviendo -1 y asignado a
              errno el valor EINTR).

       F_GETLK
              Al entrar a esta llamada, lock describe un bloqueo que nos
              gustaría 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 más 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 escritura.

       Además de ser eliminados por un F_UNLCK explícito, los bloqueos de
       registros se liberan automáticamente 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 proceso
       puede perder los bloqueos sobre un fichero como /etc/passwd o /etc/mtab
       cuando, por alguna razón, una función 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 través de execve(2).

       Debido al almacenamiento temporal que realiza stdio(3), se debería evitar
       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
       consultivos o bien obligatorios, y son consultivos por omisión. Para usar
       bloqueos obligatorios, se debe habilitar dicho tipo de bloqueo en el
       sistema de ficheros que contiene el fichero a bloquear (usando la opción
       "-o mand" en mount(8)) y en el propio fichero (deshabilitando el permiso
       de ejecución para el grupo y activado el bit de permiso set-GID).

       Los bloqueos consultivos no son de obligado cumplimiento y sólo son
       útiles entre procesos que cooperan. Los bloqueos obligatorios son
       respetados por todos los procesos.

   Manejo de señales
       F_GETOWN, F_SETOWN, F_GETSIG y F_SETSIG se utilizan para gestionar las
       señales de disponibilidad de E/S:

       F_GETOWN
              Obtiene el ID de proceso o el grupo de procesos que actualmente
              recibe las señales 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
              señales SIGIO y SIGURG para los eventos sobre el descriptor de
              fichero fd.

              Los grupos de procesos se especifican mediante valores negativos.
              (Se puede usar F_SETSIG para especificar una señal diferente 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 señal SIGIO
              cuando sea posible la entrada o la salida sobre ese descriptor de
              fichero.

              El proceso o el grupo de procesos que recibirá la señal se puede
              seleccionar usando la orden F_SETOWN de la función fcntl.  Si el
              descriptor de fichero es un conector (``socket''), esto también
              seleccionará al recipiente de las señales SIGURG que se entregan
              cuando llegan datos fuera de orden (``out-of-band'', OOB) sobre el
              enchufe. (SIGURG se envía en cualquier situación en la que
              select(2) informaría que el conector tiene una "condición
              excepcional"). Si el descriptor de fichero corresponde a un
              dispositivo de terminal, entonces las señales SIGIO se envían al
              grupo de procesos en primer plano de la terminal.

       F_GETSIG
              Obtiene la señal enviada cuando la entrada o la salida son
              posibles. Un valor cero significa que se envía SIGIO. Cualquier
              otro valor (incluyendo SIGIO) es la señal enviada en su lugar y en
              este caso se dispone de información adicional para el manejador de
              señal si éste se instala con SA_SIGINFO.

       F_SETSIG
              Establece la señal enviada cuando la entrada o la salida son
              posibles. Un valor cero significa enviar la señal por defecto
              SIGIO. Cualquier otro valor (incluyendo SIGIO) es la señal a
              enviar en su lugar y en este caso se dispone de información
              adiciona para el manejador de señal si éste se instala con
              SA_SIGINFO.

              Usando F_SETSIF con un valor distinto de cero y asignando
              SA_SIGINFO para el manejador de señal (vea sigaction(2)), se pasa
              información 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 están disponibles para E/S, debería usar
              los mecanismos usuales (select(2), poll(2), read(2) con O_NONBLOCK
              activo, etc.).

              Seleccionando una señal de tiempo real POSIX.1b (valor >=
              SIGRTMIN), se pueden encolar varios eventos de E/S usando los
              mismos números de señal. (El encolamiento depende de la memoria
              disponible). Se dispone de información extra si se asigna
              SA_SIGINFO al manejador de señal, como antes.

       Usando estos mecanismos, un programa puede implementar E/S totalmente
       asíncrona, sin usar select(2) ni poll(2) la mayor parte del tiempo.

       El uso de O_ASYNC, F_GETOWN y F_SETOWN es específico de Linux y BSD.
       F_GETSIG y F_SETSIG son específicos de Linux. POSIX posee E/S asíncrona y
       la estructura aio_sigevent para conseguir cosas similares; éstas también
       están 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
       (respectivamente) para establecer y obtener la configuración actual del
       arrendamiento 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 notifica
       (mediante el envío de una señal) cuándo otro proceso (el "competidor")
       intenta abrir (open(2)) o truncar (truncate(2)) ese fichero.

       F_SETLEASE
              Establece o elimina un arrendamiento de fichero según 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. Sólo se puede colocar un
                     arrendamiento de escritura en un fichero cuando ningún otro
                     proceso lo tenga abierto en ese momento.

              F_UNLCK
                     Elimina nuestro arrendamiento del fichero.

       Un proceso sólo puede tener un tipo de arrendamiento sobre un fichero.

       Los arrendamientos sólo se pueden obtener para ficheros regulares. Un
       proceso normal sólo 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
              referenciado 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
              arrendamiento alguno sobre el fichero.  (El tercer argumento de
              fcntl() se omite.)

       Cuando el competidor realiza un open() o truncate() que entra en
       conflicto con un arrendamiento establecido mediante F_SETLEASE, el núcleo
       bloquea la llamada al sistema (a menos que se especifique la opción
       O_NONBLOCK en open(), en cuyo caso la llamada regresa inmediatamente con
       el error EWOULDBLOCK).  El núcleo entonces notifica al arrendatario
       enviándole una señal (SIGIO por omisión).  El arrendatario debe responder
       a la recepción de esta señal haciendo cualquier limpieza que sea
       necesaria 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 número de
       segundos especificado en /proc/sys/fs/lease-break-time y la llamada al
       sistema del competidor sigue bloqueada (es decir, el competidor no
       especificó O_NONBLOCK en su llamada open() y la llamada al sistema no ha
       sido interrumpida por un manejador de señal), entonces el núcleo pone fin
       al arrendamiento del arrendatario por la fuerza.

       Una vez que se ha eliminado voluntariamente o por la fuerza el
       arrendamiento, y suponiendo que el competidor no ha desbloqueado su
       llamada al sistema, el núcleo permite continuar a la llamada al sistema
       del competidor.

       La señal por omisión que se usa para informar al arrendatario es SIGIO,
       pero se puede cambiar usando la orden F_SETSIG de fcntl ().  Si se
       ejecuta una orden F_SETSIG (incluso una que especifique SIGIO) y el
       manejador de señal 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
       arrendamientos para varios ficheros).

   Notificación de cambios en ficheros y directorios
       F_NOTIFY
              (Linux 2.4 y posteriores) Produce una notificación 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
              máscara de bits que se especifica mediante un O-lógico de cero o
              más de los siguientes bits:


              Bit         Descripción (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 aplicación debe volver a hacer
              el registro para recibir notificaciones adicionales. Otra
              posibilidad es incluir DN_MULTISHOT en arg, en cuyo caso la
              notificación se producirá hasta que se elimine explícitamente.
              Una serie de llamadas que especifican DN_MULTISHOT es acumulativa,
              con los eventos en arg añadiéndose al conjunto ya monitorizado.
              Para desactivar la notificación de todos los eventos, haga una
              llamada F_NOTIFY especificando 0 en arg.

              La notificación se produce mediante el envío de una señal. La
              señal por omisión es SIGIO, pero se puede cambiar usando la orden
              F_SETSIG de fcntl().  En el segundo caso, el manejador de señal
              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
              notificación (útil cuando se establecen notificaciones en varios
              directorios).

              Especialmente cuando se usa DN_MULTISHOT, se debería usar una
              señal POSIX.1b de tiempo real para notificación, de tal manera que
              se pueden encolar multiples notificaciones.

VALOR DEVUELTO
       Para una llamada con éxito, el valor devuelto depende de la operación:

       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 señal 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.

ERRORES
       EACCESS o EAGAIN
              Se ha prohibido la operación debido a bloqueos mantenidos por
              otros procesos.  O se ha prohibido la operación porque el fichero
              ha sido proyectado (``mapped'') en memoria por otro proceso.

       EDEADLK
              Se ha detectado que la orden F_SETLKW especificada provocaría 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 señal.  Para
              F_GETLK y F_SETLK, la orden ha sido interrumpida por una señal
              antes de que el bloqueo se haya comprobado o adquirido. Esto
              ocurre con más 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 máximo
              permitido. Para F_SETSIG, arg no es un número de señal permitido.

       EMFILE Para F_DUPFD, el proceso ya ha llegado al número máximo 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 ``sólo añadir'' (append-only).

OBSERVACIONES
       Los errores devueltos por dup2 son distintos de aquéllos dados por
       F_DUPFD.

       Desde el núcleo 2.0, no hay interacción entre los tipos de bloqueo
       colocados 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 núcleos actuales, la
       llamada al sistema de Linux devuelve EINVAL en esta situación.

       Otros sistemas tienen más campos en struct flock como, por ejemplo,
       l_sysid.  Evidentemente, l_pid sólo no va a ser muy útil si el proceso
       que posee el bloqueo puede residir en una máquina diferente.


CONFORME A
       SVID, AT&T, POSIX, X/OPEN, BSD 4.3. Sólo 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 específicos de Linux.  F_NOTIFY, F_GETLEASE
       y F_SETLEASE son específicos de Linux.  (Defina la macro _GNU_SOURCE
       antes de incluir <fcntl.h> para obtener estas definiciones.)  Las
       banderas legales para F_GETFL/F_SETFL son aquéllas que acepta open(2) y
       varían 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.

VÉASE TAMBIÉN
       dup2(2), flock(2), lockf(3), open(2), socket(2)

       Vea también locks.txt, mandatory.txt y dnotify.txt en
       /usr/src/linux/Documentation.



Linux-2.5.18                       24-04-2002                           FCNTL(2)