archivo unix operating-system file-descriptor

unix - ¿Qué son los descriptores de archivos, explicados en términos simples?



file descriptor c (10)

  1. ¿Cuál sería una descripción más simplificada de los descriptores de archivos en comparación con los de Wikipedia? ¿Por qué son necesarios? Por ejemplo, tome los procesos de shell como un ejemplo y ¿cómo se aplica?

  2. ¿Una tabla de proceso contiene más de un descriptor de archivo? ¿Si es así por qué?


Descriptores de archivo

  • Para Kernel todos los archivos abiertos son referidos por descriptores de archivo.
  • Un descriptor de archivo es un entero no negativo.
  • Cuando abrimos un archivo existente o creamos un nuevo archivo, el núcleo devuelve un descriptor de archivo a un proceso.
  • Cuando queremos leer o escribir en un archivo, identificamos el archivo con el descriptor de archivo que se volvió a ajustar por abrir o crear, como un argumento para leer o escribir.
  • Cada proceso UNIX tiene 20 descriptores de archivo y su eliminación, numerados del 0 al 19, pero se extendió a 63 por muchos sistemas.
  • Los tres primeros ya están abiertos cuando comienza el proceso 0: la entrada estándar 1: la salida estándar 2: la salida de error estándar
  • Cuando el proceso principal realiza un proceso bifurcado, el proceso secundario hereda los descriptores de archivo de la principal.

Como una adición a otras respuestas, Unix considera todo como un sistema de archivos. Su teclado es un archivo que se lee solo desde la perspectiva del kernel. La pantalla es un archivo de solo escritura. Del mismo modo, las carpetas, los dispositivos de entrada-salida, etc. también se consideran archivos. Cada vez que se abre un archivo, por ejemplo, cuando los controladores de dispositivo [para archivos de dispositivo] solicitan un open (), o un proceso abre un archivo de usuario, el kernel asigna un descriptor de archivo, un entero que especifica el acceso a ese archivo tal que solo se lea , escriba solo etc. [para referencia: https://en.wikipedia.org/wiki/Everything_is_a_file ]


Cualquier sistema operativo tiene procesos (p) en ejecución, digamos p1, p2, p3 y así sucesivamente. Cada proceso usualmente hace un uso continuo de archivos.

Cada proceso consta de un árbol de procesos (o una tabla de procesos, en otra redacción).

Generalmente, los sistemas operativos representan cada archivo en cada proceso mediante un número (es decir, en cada árbol / tabla de procesos).

El primer archivo utilizado en el proceso es el archivo 0 , el segundo es el archivo 1 , el tercero es el archivo 2 y así sucesivamente.

Cualquier número de este tipo es un descriptor de archivo.

Los descriptores de archivo suelen ser números enteros (0, 1, 2 y no 0.5, 1.5, 2.5).

Dado que a menudo describimos los procesos como "tablas de proceso", y dado que las tablas tienen filas (entradas), podemos decir que la celda del descriptor de archivos en cada entrada se utiliza para representar la entrada completa.

De manera similar, cuando abres un socket de red, tiene un descriptor de socket.

En algunos sistemas operativos, puede quedarse sin descriptores de archivos, pero este caso es extremadamente raro, y el usuario promedio de la computadora no debería preocuparse por eso.

Los descriptores de archivos pueden ser globales (el proceso A comienza en decir 0, y termina dice en 1; el Proceso B comienza en 2 y termina en 3) y así sucesivamente, pero hasta donde sé, generalmente en los sistemas operativos modernos, el archivo los descriptores no son globales, y en realidad son específicos del proceso (el proceso A comienza en decir 0 y termina en 5, mientras que el proceso B comienza en 0 y termina en 10).


En palabras simples, cuando abre un archivo, el sistema operativo crea una entrada para representar ese archivo y almacenar la información sobre ese archivo abierto. Entonces, si hay 100 archivos abiertos en su sistema operativo, habrá 100 entradas en el sistema operativo (en algún lugar del núcleo). Estas entradas están representadas por enteros como (... 100, 101, 102 ...). Este número de entrada es el descriptor de archivo. Por lo tanto, es solo un número entero que representa de forma única un archivo abierto en el sistema operativo. Si su proceso abre 10 archivos, la tabla de Procesos tendrá 10 entradas para los descriptores de archivos.

De manera similar, cuando abre un socket de red, también está representado por un entero y se denomina descriptor de socket. Espero que entiendas.


Los descriptores de archivo son los descriptores de un archivo. Dan enlaces a un archivo. Con la ayuda de ellos podemos leer, escribir y abrir un archivo.


Más puntos con respecto al File Descriptor :

  1. File Descriptors (FD) son enteros no negativos (0, 1, 2, ...) que están asociados con archivos que se abren.

  2. 0, 1, 2 son FD estándar que corresponden a STDIN_FILENO , STDOUT_FILENO y STDERR_FILENO (definidos en unistd.h ) abiertos de forma predeterminada en nombre de shell cuando se inicia el programa.

  3. Los FD se asignan en orden secuencial, es decir, el valor entero sin asignar más bajo posible.

  4. Los FD para un proceso en particular se pueden ver en /proc/$pid/fd (en sistemas basados ​​en Unix).


Otras respuestas añadieron grandes cosas. Voy a añadir sólo mis 2 centavos.

De acuerdo con Wikipedia, sabemos con certeza: un descriptor de archivo es un entero no negativo. Lo más importante que creo que falta, sería decir:

Los descriptores de archivo están vinculados a un ID de proceso.

Sabemos que los descriptores de archivos más famosos son 0, 1 y 2. 0 corresponde a STDIN , 1 a STDOUT y 2 a STDERR .

Por ejemplo, tome los procesos de shell como un ejemplo y ¿cómo se aplica?

Echa un vistazo a este código

#>sleep 1000 & [12] 14726

Creamos un proceso con el id 14726 (PID). Usando lsof -p 14726 podemos obtener las siguientes cosas:

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sleep 14726 root cwd DIR 8,1 4096 1201140 /home/x sleep 14726 root rtd DIR 8,1 4096 2 / sleep 14726 root txt REG 8,1 35000 786587 /bin/sleep sleep 14726 root mem REG 8,1 11864720 1186503 /usr/lib/locale/locale-archive sleep 14726 root mem REG 8,1 2030544 137184 /lib/x86_64-linux-gnu/libc-2.27.so sleep 14726 root mem REG 8,1 170960 137156 /lib/x86_64-linux-gnu/ld-2.27.so sleep 14726 root 0u CHR 136,6 0t0 9 /dev/pts/6 sleep 14726 root 1u CHR 136,6 0t0 9 /dev/pts/6 sleep 14726 root 2u CHR 136,6 0t0 9 /dev/pts/6

La 4ª columna FD y la siguiente columna TIPO se corresponden con el Descriptor de archivos y el tipo de Descriptor de archivos.

Algunos de los valores para el FD pueden ser:

cwd – Current Working Directory txt – Text file mem – Memory mapped file mmap – Memory mapped device

Pero el descriptor de archivo real está bajo:

NUMBER – Represent the actual file descriptor.

El carácter después del número, es decir, "1u", representa el modo en que se abre el archivo. r para leer, w para escribir, u para leer y escribir.

TYPE especifica el tipo de archivo. Algunos de los valores de los TIPOS son:

REG – Regular File DIR – Directory FIFO – First In First Out

Pero todos los descriptores de archivos son CHR - Archivo especial de caracteres (o archivo de dispositivo de caracteres)

Ahora, podemos identificar los Descriptores de archivos para STDIN , STDOUT y STDERR fácilmente con lsof -p PID , o podemos ver lo mismo si ls /proc/PID/fd .

Tenga en cuenta también que la tabla de descriptores de archivos que el kernel realiza un seguimiento no es lo mismo que la tabla de archivos o la tabla de inodos. Estos son separados, como explicaron algunas otras respuestas.

Puede preguntarse dónde están estos descriptores de archivos físicamente y qué se almacena en /dev/pts/6 por ejemplo.

sleep 14726 root 0u CHR 136,6 0t0 9 /dev/pts/6 sleep 14726 root 1u CHR 136,6 0t0 9 /dev/pts/6 sleep 14726 root 2u CHR 136,6 0t0 9 /dev/pts/6

Bueno, /dev/pts/6 vive puramente en la memoria. Estos no son archivos normales, sino los llamados archivos de dispositivo de caracteres . Puede verificar esto con: ls -l /dev/pts/6 y comenzarán con c , en mi caso crw--w---- .

Solo para recordar la mayoría de los sistemas operativos de Linux como los que definen siete tipos de archivos:

  • Archivos regulares
  • Directorios
  • Archivos de dispositivo de caracteres
  • Bloquear archivos de dispositivo
  • Sockets de dominio local
  • Tuberías con nombre (FIFOs) y
  • Enlaces simbólicos

Un descriptor de archivo es un identificador opaco que se usa en la interfaz entre el usuario y el espacio del núcleo para identificar los recursos de archivo / socket. Por lo tanto, cuando usa open() o socket() (las llamadas del sistema para interactuar con el kernel), se le proporciona un descriptor de archivo, que es un entero (en realidad es un índice en la estructura de procesos u), pero eso no es importante ). Por lo tanto, si desea interactuar directamente con el kernel, use las llamadas del sistema para read() , write() , close() etc., el identificador que usa es un descriptor de archivos.

Hay una capa de abstracción superpuesta en las llamadas al sistema, que es la interfaz stdio . Esto proporciona más funcionalidad / características que las llamadas básicas del sistema. Para esta interfaz, el identificador opaco que obtiene es un FILE* , que es devuelto por la llamada fopen() . Hay muchas funciones que utilizan la interfaz fprintf() , fscanf() , fclose() , que están ahí para hacer tu vida más fácil. En C, stdin , stdout y stderr son FILE* , que en UNIX se asignan respectivamente a los descriptores de archivo 0 , 1 y 2 .


Descriptores de archivo (FD):

  • En Linux / Unix , todo es un archivo. Archivo regular, directorios, e incluso dispositivos son archivos. Cada archivo tiene un número asociado llamado Descriptor de archivo (FD).
  • Su pantalla también tiene un descriptor de archivos. Cuando se ejecuta un programa, la salida se envía al Descriptor de archivos de la pantalla y usted ve la salida del programa en su monitor. Si la salida se envía al Descriptor de archivos de la impresora, la salida del programa se habría impreso.

    Redirección de errores:
    Cada vez que ejecute un programa / comando en el terminal, 3 archivos siempre están abiertos
    1. entrada estándar
    2. salida estándar
    3. Error estándar.

    Estos archivos siempre están presentes cuando se ejecuta un programa. Como se explicó antes de un descriptor de archivo, está asociado con cada uno de estos archivos.
    Descriptor de archivo
    Entrada estándar STDIN 0
    Salida estándar STDOUT 1
    Error estándar STDERR 2

  • Por ejemplo, al buscar archivos, uno normalmente obtiene permisos con permiso denegado o algún otro tipo de error. Estos errores se pueden guardar en un archivo en particular.
    Ejemplo 1

$ ls mydir 2> errorsfile.txt

El descriptor de archivo para error estándar es 2.
Si no hay ningún directorio llamado mydir, la salida del comando se guardará en el archivo errorfile.txt
Usando "2>" redirigimos la salida de error a un archivo llamado "errorfile.txt"
Por lo tanto, la salida del programa no está llena de errores.

Espero que tengas tu respuesta.


Escúchalo en la boca del caballo: APUE (Richard Stevens).
Al núcleo, todos los archivos abiertos son referidos por los descriptores de archivos. Un descriptor de archivo es un número no negativo.
Cuando abrimos un archivo existente o creamos un nuevo archivo, el núcleo devuelve un descriptor de archivo al proceso. El núcleo mantiene una tabla de todos los descriptores de archivos abiertos, que están en uso. La asignación de descriptores de archivo es generalmente secuencial y se asignan al archivo como el siguiente descriptor de archivo libre del grupo de descriptores de archivo libres. Cuando cerramos el archivo, el descriptor del archivo se libera y está disponible para una nueva asignación.
Vea esta imagen para más detalles:

Cuando queremos leer o escribir un archivo, identificamos el archivo con el descriptor de archivo que fue devuelto por la llamada a la función open () o create () , y lo usamos como un argumento para leer () o escribir () .
Por convención, las carcasas del sistema UNIX asocian el descriptor de archivo 0 con la entrada estándar de un proceso, el descriptor de archivo 1 con la salida estándar y el desciptor de archivo 2 con el error estándar .
El descriptor de archivo varía de 0 a OPEN_MAX.
Para más información, lea el tercer capítulo del libro APUE.