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

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

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

Nishant
fuente
3
¿Qué pasa con los conceptos de stdin stdout stderr, etc.? Tengo una instancia como decir que el proceso del navegador se abrió y ha abierto algunos archivos temporales para mostrar mi html. El proceso utiliza el mismo fd para leer / escribir? También la tabla de procesos ... tiene entradas como fd0 pointer fd1 pointer fd2 pointer ..... ¿eso significa que todos estos archivos están en RAM? ¿Por qué más punteros?
Nishant
43
Cuando abre un archivo, el sistema operativo crea una secuencia a ese archivo y conecta esa secuencia al archivo abierto, el descriptor de hecho representa esa secuencia. Del mismo modo, hay algunas transmisiones predeterminadas creadas por el sistema operativo. Estas transmisiones están conectadas a su terminal en lugar de archivos. Entonces, cuando escribes algo en la terminal, va a stdin stream y OS. Y cuando escribe el comando "ls" en la terminal, el sistema operativo escribe la salida en la secuencia estándar. La transmisión estándar está conectada a la terminal del monitor para que pueda ver la salida allí.
Tayyab
1
Con respecto al ejemplo del navegador, no es necesario que el navegador mantenga abiertos los archivos. Depende de la implementación del navegador, pero en la mayoría de los casos el navegador abre un archivo temporal, escribe el archivo y cierra el archivo, por lo que no es necesario que el archivo se abra incluso si la página web está abierta. Y el descriptor solo contiene la información del archivo y no necesariamente mantiene el archivo en la RAM. Cuando lee los datos de un descriptor, el sistema operativo lee los datos del disco duro. La información en el descriptor de archivo solo representa la ubicación del archivo en el disco duro, etc.
Tayyab
55
El descriptor de archivo a archivo no es un mapeo uno a uno. Podría abrir () el mismo archivo 4 veces y obtener 4 descriptores de archivo diferentes. Cada uno de los cuales podría usarse (dependiendo de los indicadores pasados ​​a open ()) para leer, escribir o ambos. En cuanto a si el archivo vive en la RAM o en el disco, el núcleo y sus diversas cachés lo ocultan. Finalmente, qué es el caché coincidirá con lo que está en el disco (para escritura), y el núcleo no volverá al disco, para leer, si los datos ya están en el caché.
Beano
77
Este es un buen artículo para entenderlo fácilmente bottomupcs.com/file_descriptors.xhtml
Krishan Gopal

Respuestas:

562

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, entonces 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 exclusiva un archivo abierto en el sistema operativo. Si su proceso abre 10 archivos, su tabla de Proceso tendrá 10 entradas para los descriptores de archivo.

De manera similar, cuando abre un socket de red, también está representado por un número entero y se llama Socket Descriptor. Espero que entiendas.

Tayyab
fuente
8
Además, esta es la razón por la que puede quedarse sin descriptores de archivo, si abre muchos archivos a la vez. Lo que evitará que los sistemas * nix se ejecuten, ya que abren descriptores a cosas /proctodo el tiempo.
Spencer Rathbun
8
@ErbenMo: No, puede que no sea lo mismo. Cuando abra el archivo, el sistema operativo asignará un FD que esté disponible y cuando lo cierre, el sistema operativo liberará el FD y puede asignar ese FD a otro archivo abierto después de eso. La forma en que su sistema operativo rastrea los archivos abiertos y no tiene nada que ver con un archivo específico.
Tayyab
49
" Por lo tanto, es solo un número entero que representa de forma exclusiva un archivo abierto en el sistema operativo " . Esto es incorrecto. Ese entero representa únicamente un archivo abierto dentro de un proceso . El descriptor de archivo 0, por ejemplo, representará un archivo abierto en un proceso y un archivo abierto completamente diferente en otro proceso.
Keith Thompson el
15
@Tayyab: Creo que te equivocas. Los descriptores de archivo 0, 1 y 2 son entrada estándar, salida estándar y error estándar para cada proceso en ejecución. Una llamada inicial exitosa a open()le dará el descriptor de archivo 3, incluso si otro proceso en ejecución tiene un descriptor de archivo 3. Vea la definición POSIX deopen() : "La función open () devolverá un descriptor de archivo para el archivo nombrado que es el más bajo el descriptor de archivo no está abierto actualmente para ese proceso ". (énfasis añadido).
Keith Thompson el
17
@KeithThompson: Sí, tienes razón. En realidad se trata del nivel de abstracción. En realidad, se mantienen dos tablas, donde la primera es por proceso y la segunda es para todo el sistema. FD en la tabla por proceso (es decir, fdtable) no es único en todo el sistema. Sin embargo, se asigna a la tabla v-node que contiene las entradas únicas del sistema. Entonces, cuando llama a la función fopen () y fileno () para verificar el descriptor, puede obtener el mismo número FD en 2 procesos diferentes porque devuelve el índice de fdtable que es por proceso. ¡¡Gracias por sacar el tema!!
Tayyab
116

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()(el sistema llama a la interfaz con el núcleo), se le da un descriptor de archivo, que es un número entero (en realidad es un índice de la estructura de procesos u, pero eso no es importante). Por lo tanto, si desea interactuar directamente con el núcleo, usando las llamadas al sistema a read(), write(), close()etc el mango que se utiliza es un descriptor de archivo.

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

Comilona
fuente
66
Personalmente, creo que esta respuesta es mejor que la marcada como respuesta. Votado
Tarik
101

Escuche de boca de caballo: APUE (Richard Stevens).
Para el kernel, todos los archivos abiertos son referidos por File Descriptors. 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 conjunto de descriptores de archivo libre. Cuando cerramos el archivo, el descriptor del archivo se libera y está disponible para su posterior asignación.
Vea esta imagen para más detalles:

Dos procesos

Cuando deseamos leer o escribir un archivo, identificamos el archivo con el descriptor de archivo que fue devuelto por la función open () o create () , y lo usamos como argumento para leer () o escribir () .
Por convención, los shells del sistema UNIX asocian el descriptor de archivo 0 con la entrada estándar de un proceso, el descriptor de archivo 1 con salida estándar y el descriptor de archivo 2 con error estándar .
El descriptor de archivo varía de 0 a OPEN_MAX. El valor máximo del descriptor de archivo se puede obtener con ulimit -n. Para obtener más información, consulte el tercer capítulo del Libro APUE.

Shekhar Kumar
fuente
1
Dado que 0, 1, 2 están asociados con "stdin", "stdout" y "stderr" de un proceso, ¿podemos usar esos descriptores al mismo tiempo para diferentes procesos?
Tarik
@Tarik: los descriptores de archivo son por proceso. Para ver esto, descargue osquery y ejecútelo osqueryi <<< echo '.all process_open_files'en un shell bash.
Ben Creasy
29

Otras respuestas agregaron cosas geniales. Agregaré solo mis 2 centavos.

Según Wikipedia, estamos seguros: un descriptor de archivo es un número entero no negativo. Lo más importante que creo que falta es decir:

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

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

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

Mira este código

#>sleep 1000 &
[12] 14726

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

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 TYPE corresponden al descriptor de archivo y al tipo de descriptor de archivo.

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á debajo:

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 TYPE son:

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

Pero todos los descriptores de archivo son CHR: archivo especial de caracteres (o archivo de dispositivo de caracteres)

Ahora, podemos identificar los Descriptores de archivos para STDIN, STDOUTy STDERRfácil con lsof -p PID, o podemos ver lo mismo si lo hacemos ls /proc/PID/fd.

Tenga en cuenta también que la tabla de descriptores de archivos que el núcleo realiza un seguimiento no es la misma que la tabla de archivos o la tabla de inodes. Estos están separados, como explicaron algunas otras respuestas.

tabla fd

Puede preguntarse dónde están físicamente estos descriptores de archivos y qué se almacena, /dev/pts/6por 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/6vive puramente en la memoria. Estos no son archivos normales, sino los llamados archivos de dispositivos de caracteres . Puede verificar esto con: ls -l /dev/pts/6y comenzarán con c, en mi caso crw--w----.

Solo para recordar que la mayoría de Linux como SO define siete tipos de archivos:

  • Archivos regulares
  • Directorios
  • Archivos de dispositivos de caracteres
  • Bloquear archivos de dispositivo
  • Sockets de dominio local
  • Tuberías con nombre (FIFOs) y
  • Enlaces simbólicos
prosti
fuente
1
Gracias. De hecho, es importante señalar que es por proceso. Ayuda a visualizar mejor las cosas.
Nishant
1
Los tipos de archivos definidos por el sistema operativo, que ha mencionado en su respuesta, realmente ayudan a comprender los archivos en un nivel inferior.
Rohan Bhale
20

Más puntos con respecto a File Descriptor:

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

  2. 0, 1, 2son FD estándar que corresponden a STDIN_FILENO, STDOUT_FILENOy STDERR_FILENO(definidos en unistd.h) se abren por defecto en nombre del shell cuando se inicia el programa.

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

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

Sandeep_black
fuente
16

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 núcleo. La pantalla es un archivo de solo escritura. Del mismo modo, las carpetas, los dispositivos de entrada y salida, etc., también se consideran archivos. Cada vez que se abre un archivo, digamos que cuando los controladores de dispositivo [para archivos de dispositivo] solicitan un open (), o un proceso abre un archivo de usuario, el núcleo asigna un descriptor de archivo, un número entero que especifica el acceso a ese archivo para que sea de solo lectura , escriba solo etc. [para referencia: https://en.wikipedia.org/wiki/Everything_is_a_file ]

Balu
fuente
Los descriptores de archivos también pueden referirse a cosas que no existen en el sistema de archivos, como tuberías anónimas y tomas de red.
kbolino
12

Descriptores de archivo (FD):

  • En Linux / Unix , todo es un archivo. Los archivos normales, los directorios e incluso los dispositivos son archivos. Cada archivo tiene un número asociado llamado Descriptor de archivo (FD).
  • Su pantalla también tiene un Descriptor de archivo. Cuando se ejecuta un programa, la salida se envía al Descriptor de archivo 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 ejecuta un programa / comando en la terminal, siempre hay 3 archivos 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.
    Archivo                                        Descriptor de archivo
    Entrada estándar STDIN 0
    Salida estándar STDOUT 1
    Error estándar STDERR 2

  • Por ejemplo, al buscar archivos, normalmente se obtienen permisos denegados 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 el 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>" redirigiremos la salida del error a un archivo llamado "errorfile". txt "
Por lo tanto, la salida del programa no está llena de errores.

Espero que hayas recibido tu respuesta.

Abhishek Kamal
fuente
5

Cualquier sistema operativo tiene procesos (p's) ejecutándose, digamos p1, p2, p3, etc. Cada proceso generalmente hace un uso continuo de los archivos.

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

Por lo general, los sistemas operativos representan cada archivo en cada proceso por un número (es decir, en cada árbol / tabla de proceso).

El primer archivo utilizado en el proceso es file0 , el segundo es file1 , el tercero es file2 , y así sucesivamente.

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

Los descriptores de archivos suelen ser 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 archivo en cada entrada, se utiliza para representar la entrada completa.

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

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

Los descriptores de archivo pueden ser globales (el proceso A comienza en decir 0 y termina en 1; el proceso B comienza en 2 y termina en 3) y así sucesivamente, pero hasta donde yo 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 digamos 0 y finaliza en 5, mientras que el proceso B comienza en 0 y finaliza en 10).


fuente
Lea más sobre FD en Linux aquí: unix.stackexchange.com/questions/358022/…
1
gran respuesta :)
humble_wolf
5

Descriptores de archivo

  • Para Kernel, todos los archivos abiertos se denominan descriptores de archivo.
  • Un descriptor de archivo es un entero no negativo.
  • Cuando abrimos un archivo existente o creamos un archivo nuevo, el núcleo devuelve un descriptor de archivo a un proceso.
  • Cuando deseamos leer o escribir en un archivo, identificamos el archivo con un descriptor de archivo que fue reajustado por abrir o crear, como argumento para leer o escribir.
  • Cada proceso UNIX tiene 20 descriptores de archivos y su eliminación, numerados del 0 al 19, pero muchos sistemas lo ampliaron a 63.
  • Los primeros tres 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 padre bifurca un proceso, el proceso hijo hereda los descriptores de archivo del padre
Mahendra Suthar
fuente
1

Además de sobre todo las respuestas simplificadas.
Si está trabajando con archivos en script bash, es mejor usar el descriptor de archivos.
Por ejemplo: -
Desea leer y escribir desde / al archivo "test.txt".
Use el descriptor de archivo como se muestra a continuación

FILE=$1 # give the name of file in the command line
exec 5<>$FILE # '5' here act as the file descriptor
# Reading from the file line by line using file descriptor
while read LINE; do
    echo "$LINE"
done <&5

# Writing to the file using descriptor
echo "Adding the date: `date`" >&5 
exec 5<&- # Closing a file descriptor
sumitsinghdeode
fuente
-5

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.

Motimahal
fuente