Was sind Dateideskriptoren, die in einfachen Worten erklärt werden?

383
  1. Was wäre eine vereinfachte Beschreibung von Dateideskriptoren im Vergleich zu Wikipedia? Warum werden sie benötigt? Nehmen wir als Beispiel Shell-Prozesse und wie trifft dies zu?

  2. Enthält eine Prozesstabelle mehr als einen Dateideskriptor? Wenn ja, warum?

Nishant
quelle
3
Was ist mit den Konzepten von stdin stdout stderr etc? Ich habe eine Instanz wie beispielsweise den Browserprozess geöffnet und einige temporäre Dateien für die Anzeige meines HTML-Codes geöffnet. Der Prozess verwendet die gleiche fd zum Lesen / Schreiben? Auch die Prozesstabelle ....... hat Einträge wie fd0 Zeiger fd1 Zeiger fd2 Zeiger ..... bedeutet das, dass sich alle diese Dateien im RAM befinden? Warum sonst Zeiger?
Nishant
43
Wenn Sie eine Datei öffnen, erstellt das Betriebssystem einen Stream zu dieser Datei und verbindet diesen Stream mit der geöffneten Datei. Der Deskriptor repräsentiert diesen Stream tatsächlich. Ebenso gibt es einige vom Betriebssystem erstellte Standard-Streams. Diese Streams sind anstelle von Dateien mit Ihrem Terminal verbunden. Wenn Sie also etwas in das Terminal schreiben, geht es zu stdin stream und OS. Wenn Sie den Befehl "ls" auf das Terminal schreiben, schreibt das Betriebssystem die Ausgabe in den stdout-Stream. Der stdout-Stream ist mit Ihrem Monitor-Terminal verbunden, sodass Sie die Ausgabe dort sehen können.
Tayyab
1
In Bezug auf das Browserbeispiel ist es nicht erforderlich, dass der Browser die Dateien geöffnet hält. Dies hängt von der Implementierung des Browsers ab. In den meisten Fällen öffnet der Browser jedoch eine temporäre Datei, schreibt die Datei und schließt sie. Daher ist es nicht erforderlich, dass die Datei geöffnet wird, auch wenn die Webseite geöffnet ist. Und der Deskriptor enthält nur die Informationen der Datei und hält die Datei nicht unbedingt im RAM. Wenn Sie die Daten von einem Deskriptor lesen, liest das Betriebssystem die Daten von der Festplatte. Die Informationen im Dateideskriptor stellen nur den Speicherort der Datei auf der Festplatte usw. dar.
Tayyab
5
Der Dateideskriptor für die Datei ist keine Eins-zu-Eins-Zuordnung. Ich konnte dieselbe Datei viermal öffnen () und vier verschiedene Dateideskriptoren erhalten. Jedes davon kann (abhängig von den an open () übergebenen Flags) zum Lesen, Schreiben oder für beides verwendet werden. Ob sich die Datei im RAM oder auf der Festplatte befindet - dies wird Ihnen vom Kernel und seinen verschiedenen Caches verborgen. Letztendlich stimmt der Cache mit dem auf der Festplatte (zum Schreiben) überein, und der Kernel kehrt zum Lesen nicht auf die Festplatte zurück, wenn sich die Daten bereits im Cache befinden.
Beano
7
Dies ist ein guter Artikel, um es leicht zu verstehen bottomupcs.com/file_descriptors.xhtml
Krishan Gopal

Antworten:

561

Mit einfachen Worten, wenn Sie eine Datei öffnen, erstellt das Betriebssystem einen Eintrag, um diese Datei darzustellen und die Informationen zu dieser geöffneten Datei zu speichern. Wenn also 100 Dateien in Ihrem Betriebssystem geöffnet sind, gibt es 100 Einträge im Betriebssystem (irgendwo im Kernel). Diese Einträge werden durch ganze Zahlen wie (... 100, 101, 102 ....) dargestellt. Diese Eintragsnummer ist der Dateideskriptor. Es handelt sich also nur um eine Ganzzahl, die eine geöffnete Datei im Betriebssystem eindeutig darstellt. Wenn Ihr Prozess 10 Dateien öffnet, enthält Ihre Prozesstabelle 10 Einträge für Dateideskriptoren.

Wenn Sie einen Netzwerk-Socket öffnen, wird dieser ebenfalls durch eine Ganzzahl dargestellt und als Socket-Deskriptor bezeichnet. Ich hoffe, Sie verstehen.

Tayyab
quelle
7
Aus diesem Grund können Ihnen auch die Dateideskriptoren ausgehen, wenn Sie viele Dateien gleichzeitig öffnen. Dies verhindert, dass * nix-Systeme ausgeführt werden, da sie /procständig Deskriptoren öffnen .
Spencer Rathbun
8
@ErbenMo: Nein, es kann nicht dasselbe sein. Wenn Sie eine Datei öffnen, weist das Betriebssystem einen verfügbaren FD zu. Wenn Sie ihn schließen, gibt das Betriebssystem den FD frei und weist diesen FD möglicherweise einer anderen danach geöffneten Datei zu. Die Methode des Betriebssystems zum Öffnen geöffneter Dateien hat nichts mit einer bestimmten Datei zu tun.
Tayyab
49
" Es ist also nur eine Ganzzahl, die eine geöffnete Datei im Betriebssystem eindeutig darstellt. " Dies ist falsch. Diese Ganzzahl repräsentiert eindeutig eine geöffnete Datei innerhalb eines Prozesses . Der Dateideskriptor 0 repräsentiert beispielsweise eine geöffnete Datei in einem Prozess und eine völlig andere geöffnete Datei in einem anderen Prozess.
Keith Thompson
15
@ Tayyab: Ich glaube du liegst falsch. Die Dateideskriptoren 0, 1 und 2 sind Standardeingabe, Standardausgabe und Standardfehler für jeden laufenden Prozess. Ein erfolgreicher erster Aufruf von open()gibt Ihnen den Dateideskriptor 3, auch wenn ein anderer laufender Prozess zufällig einen Dateideskriptor 3 hat. Siehe die POSIX-Definition vonopen() : "Die Funktion open () gibt einen Dateideskriptor für die benannte Datei zurück, der der niedrigste ist Dateideskriptor für diesen Prozess derzeit nicht geöffnet . " (Betonung hinzugefügt).
Keith Thompson
17
@ KeithThompson: Ja, du hast recht. Eigentlich geht es um die Abstraktionsebene. Tatsächlich werden zwei Tabellen verwaltet, wobei die erste pro Prozess und die zweite systemweit ist. FD in der Prozesstabelle (dh fdtable) ist systemweit nicht eindeutig. Es wird jedoch einer V-Node-Tabelle zugeordnet, die die systemweiten eindeutigen Einträge enthält. Wenn Sie also die Funktionen fopen () und fileno () aufrufen, um den Deskriptor zu überprüfen, können Sie dieselbe FD-Nummer in zwei verschiedenen Prozessen erhalten, da der Index von fdtable zurückgegeben wird, der pro Prozess angegeben ist. Danke, dass du es angesprochen hast !!
Tayyab
116

Ein Dateideskriptor ist ein undurchsichtiges Handle, das in der Schnittstelle zwischen Benutzer- und Kernelbereich verwendet wird, um Datei- / Socket-Ressourcen zu identifizieren. Wenn Sie also open()oder socket()(Systemaufrufe zur Schnittstelle zum Kernel) verwenden, erhalten Sie einen Dateideskriptor, der eine Ganzzahl ist (es ist tatsächlich ein Index für die Prozess-u-Struktur - aber das ist nicht wichtig). Wenn Sie eine direkte Schnittstelle zum Kernel, Systemaufrufe usw. verwenden möchten read(), write()ist close()das von Ihnen verwendete Handle daher ein Dateideskriptor.

Den Systemaufrufen wird eine Abstraktionsebene überlagert, bei der es sich um die stdioSchnittstelle handelt. Dies bietet mehr Funktionen / Features als die grundlegenden Systemaufrufe. Für diese Schnittstelle ist das undurchsichtige Handle ein FILE*, das vom fopen()Aufruf zurückgegeben wird. Es gibt viele , viele Funktionen, die die Verwendung stdioSchnittstelle fprintf(), fscanf(), fclose(), die gibt es Ihnen das Leben leichter zu machen. In C stdin, stdoutund stderrsind FILE*, die in UNIX Karte jeweils Dateideskriptoren 0, 1und 2.

Beano
quelle
6
Ich persönlich denke, dass diese Antwort besser ist als die als Antwort gekennzeichnete. Upvoted.
Tarik
101

Hören Sie es aus dem Maul des Pferdes: APUE (Richard Stevens).
Für den Kernel werden alle geöffneten Dateien von Dateideskriptoren referenziert. Ein Dateideskriptor ist eine nicht negative Zahl.

Wenn wir eine vorhandene Datei öffnen oder eine neue Datei erstellen, gibt der Kernel einen Dateideskriptor an den Prozess zurück. Der Kernel verwaltet eine Tabelle aller geöffneten Dateideskriptoren, die verwendet werden. Die Zuweisung von Dateideskriptoren erfolgt im Allgemeinen sequentiell und sie werden der Datei als nächster freier Dateideskriptor aus dem Pool der freien Dateideskriptoren zugewiesen. Wenn wir die Datei schließen, wird der Dateideskriptor freigegeben und steht für die weitere Zuordnung zur Verfügung.
Siehe dieses Bild für weitere Details:

Zwei Prozesse

Wenn wir eine Datei lesen oder schreiben möchten, identifizieren wir die Datei mit dem Dateideskriptor, der vom Funktionsaufruf open () oder create () zurückgegeben wurde , und verwenden ihn als Argument für read () oder write () .
Es ist üblich, dass UNIX-System-Shells den Dateideskriptor 0 mit der Standardeingabe eines Prozesses, den Dateideskriptor 1 mit der Standardausgabe und den Dateideskriptor 2 mit dem Standardfehler verknüpfen .
Der Dateideskriptor reicht von 0 bis OPEN_MAX. Der maximale Wert des Dateideskriptors kann mit erhalten werden ulimit -n. Weitere Informationen finden Sie im 3. Kapitel des APUE-Buches.

Shekhar Kumar
quelle
1
Können wir diese Deskriptoren gleichzeitig für verschiedene Prozesse verwenden, da 0, 1, 2 mit "stdin", "stdout" und "stderr" eines Prozesses verknüpft sind?
Tarik
@Tarik: Dateideskriptoren sind pro Prozess. Laden Sie dazu osquery herunter und führen Sie es osqueryi <<< echo '.all process_open_files'in einer Bash-Shell aus.
Ben Creasy
29

Andere Antworten fügten großartige Dinge hinzu. Ich werde nur meine 2 Cent hinzufügen.

Laut Wikipedia wissen wir sicher: Ein Dateideskriptor ist eine nicht negative Ganzzahl. Das Wichtigste, was mir fehlt, wäre zu sagen:

Dateideskriptoren sind an eine Prozess-ID gebunden.

Wir wissen, dass die bekanntesten Dateideskriptoren 0, 1 und 2 sind. 0 entspricht STDIN, 1 bis STDOUTund 2 bis STDERR.

Nehmen wir als Beispiel Shell-Prozesse und wie trifft dies zu?

Überprüfen Sie diesen Code

#>sleep 1000 &
[12] 14726

Wir haben einen Prozess mit der ID 14726 (PID) erstellt. Mit dem können lsof -p 14726wir die Dinge wie folgt bekommen:

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

Die 4. Spalte FD und die nächste Spalte TYPE entsprechen dem Dateideskriptor und dem Dateideskriptortyp.

Einige der Werte für die FD können sein:

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

Der eigentliche Dateideskriptor befindet sich jedoch unter:

NUMBER – Represent the actual file descriptor. 

Das Zeichen nach der Zahl, dh "1u", repräsentiert den Modus, in dem die Datei geöffnet wird. r zum Lesen, w zum Schreiben, u zum Lesen und Schreiben.

TYPE gibt den Dateityp an. Einige der Werte von TYPEs sind:

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

Alle Dateideskriptoren sind jedoch CHR - Character Special File (oder Character Device File).

Jetzt können wir die Dateideskriptoren für identifizieren STDIN, STDOUTund STDERReinfach mit lsof -p PID, oder wir können das gleiche , wenn wir sehen ls /proc/PID/fd.

Beachten Sie auch, dass die Dateideskriptortabelle, die der Kernel verfolgt, nicht mit der Dateitabelle oder der Inodes-Tabelle identisch ist. Diese sind getrennt, wie einige andere Antworten erklärt haben.

fd Tabelle

Sie fragen sich, wo diese Filedeskriptoren physisch sind und was gespeichert ist /dev/pts/6zum Beispiel

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

Nun, /dev/pts/6lebt nur in Erinnerung. Dies sind keine regulären Dateien, sondern sogenannte Zeichengerätedateien . Sie können dies überprüfen mit: ls -l /dev/pts/6und sie beginnen cin meinem Fall mit crw--w----.

Um sich an die meisten Linux-ähnlichen Betriebssysteme zu erinnern, definieren Sie sieben Dateitypen:

  • Normale Dateien
  • Verzeichnisse
  • Zeichengerätedateien
  • Gerätedateien blockieren
  • Lokale Domain-Sockets
  • Named Pipes (FIFOs) und
  • Symbolische Links
Prosti
quelle
1
Vielen Dank. In der Tat ist es wichtig darauf hinzuweisen, dass es pro Prozess ist! Es hilft, die Dinge besser zu visualisieren.
Nishant
1
Die vom Betriebssystem definierten Dateitypen, die Sie in Ihrer Antwort erwähnt haben, helfen wirklich dabei, Dateien auf einer niedrigeren Ebene zu verstehen.
Rohan Bhale
20

Weitere Punkte zu File Descriptor:

  1. File Descriptors(FD) sind nicht negative Ganzzahlen (0, 1, 2, ...), die geöffneten Dateien zugeordnet sind.

  2. 0, 1, 2ist Standard FD ‚Das entspricht s STDIN_FILENO, STDOUT_FILENOund STDERR_FILENO(definiert in unistd.hstandardmäßig im Namen von Shell , wenn die Programmstarts geöffnet).

  3. FDs werden in der sequentiellen Reihenfolge zugewiesen, was den niedrigstmöglichen nicht zugewiesenen ganzzahligen Wert bedeutet.

  4. FDs für einen bestimmten Prozess sind in /proc/$pid/fd(auf Unix-basierten Systemen) zu sehen.

Sandeep_black
quelle
16

Als Ergänzung zu anderen Antworten betrachtet Unix alles als Dateisystem. Ihre Tastatur ist eine Datei, die nur aus der Sicht des Kernels gelesen werden kann. Der Bildschirm ist eine Nur-Schreib-Datei. Ebenso werden Ordner, Eingabe- / Ausgabegeräte usw. als Dateien betrachtet. Wenn eine Datei geöffnet wird, z. B. wenn die Gerätetreiber [für Gerätedateien] ein open () anfordern oder ein Prozess eine Benutzerdatei öffnet, weist der Kernel einen Dateideskriptor zu, eine Ganzzahl, die den Zugriff auf diese Datei angibt, sodass sie schreibgeschützt ist , schreibe nur usw. [als Referenz: https://en.wikipedia.org/wiki/Everything_is_a_file ]

Balu
quelle
Dateideskriptoren können sich auch auf Dinge beziehen, die im Dateisystem nicht vorhanden sind, wie anonyme Pipes und Netzwerk-Sockets.
Kbolino
12

Dateideskriptoren (FD):

  • Unter Linux / Unix ist alles eine Datei. Normale Dateien, Verzeichnisse und sogar Geräte sind Dateien. Jeder Datei ist eine Nummer zugeordnet, die als File Descriptor (FD) bezeichnet wird.
  • Ihr Bildschirm verfügt außerdem über einen Dateideskriptor. Wenn ein Programm ausgeführt wird, wird die Ausgabe an den Dateideskriptor des Bildschirms gesendet, und Sie sehen die Programmausgabe auf Ihrem Monitor. Wenn die Ausgabe an den Dateideskriptor des Druckers gesendet wird, wurde die Programmausgabe gedruckt.

    Fehlerumleitung:
    Immer wenn Sie ein Programm / einen Befehl am Terminal ausführen, sind 3 Dateien geöffnet
    1. Standardeingabe
    2. Standardausgabe
    3. Standart Fehler.

    Diese Dateien sind immer vorhanden, wenn ein Programm ausgeführt wird. Wie bereits erläutert, ist jeder dieser Dateien ein Dateideskriptor zugeordnet.
    Datei                                        - File Descriptor
    Standardeingabe STDIN 0
    Standardausgabe STDOUT 1
    Standardfehler STDERR 2

  • Beispielsweise erhält man bei der Suche nach Dateien normalerweise Fehler, denen die Berechtigung verweigert wurde, oder eine andere Art von Fehlern. Diese Fehler können in einer bestimmten Datei gespeichert werden.
    Beispiel 1

$ ls mydir 2> Errorsfile.txt

Der Dateideskriptor für Standardfehler ist 2.
Wenn kein Verzeichnis mit dem Namen mydir vorhanden ist, wird die Ausgabe des Befehls in der Datei errorfile.txt gespeichert.
Mit "2>" leiten wir die Fehlerausgabe in eine Datei mit dem Namen "errorfile" um. txt "
Somit ist die Programmausgabe nicht mit Fehlern überfüllt.

Ich hoffe du hast deine Antwort bekommen.

Abhishek Kamal
quelle
5

Auf jedem Betriebssystem werden Prozesse ( ps ) ausgeführt, z. B. p1, p2, p3 usw. Bei jedem Prozess werden normalerweise Dateien fortlaufend verwendet.

Jeder Prozess besteht aus einem Prozessbaum (oder einer Prozesstabelle in einer anderen Formulierung).

Normalerweise stellen Betriebssysteme jede Datei in jedem Prozess durch eine Zahl dar (dh in jedem Prozessbaum / jeder Tabelle).

Die erste im Prozess verwendete Datei ist Datei0 , die zweite ist Datei1 , die dritte ist Datei2 und so weiter.

Jede solche Nummer ist ein Dateideskriptor.

Dateideskriptoren sind normalerweise ganze Zahlen (0, 1, 2 und nicht 0,5, 1,5, 2,5).

Da wir Prozesse häufig als "Prozesstabellen" beschreiben und Tabellen Tabellen (Einträge) enthalten, können wir sagen, dass die Dateideskriptorzelle in jedem Eintrag den gesamten Eintrag darstellt.

In ähnlicher Weise verfügt ein Netzwerk-Socket beim Öffnen über einen Socket-Deskriptor.

In einigen Betriebssystemen gehen Ihnen möglicherweise die Dateideskriptoren aus, aber ein solcher Fall ist äußerst selten, und der durchschnittliche Computerbenutzer sollte sich darüber keine Sorgen machen.

Dateideskriptoren können global sein (Prozess A beginnt mit 0 und endet mit 1; Prozess B beginnt mit 2 und endet mit 3) und so weiter, aber soweit ich weiß, normalerweise in modernen Betriebssystemen, Datei Deskriptoren sind nicht global und tatsächlich prozessspezifisch (Prozess A beginnt mit 0 und endet mit 5, während Prozess B mit 0 beginnt und mit 10 endet).


quelle
Lesen Sie mehr über FDs unter
1
tolle Antwort :)
bescheidene_wolf
5

Dateideskriptoren

  • Für den Kernel werden alle geöffneten Dateien von Dateideskriptoren referenziert.
  • Ein Dateideskriptor ist eine nicht negative Ganzzahl.
  • Wenn wir eine vorhandene Datei öffnen oder eine neue Datei erstellen, gibt der Kernel einen Dateideskriptor an einen Prozess zurück.
  • Wenn wir eine Datei lesen oder schreiben möchten, identifizieren wir die Datei mit dem Dateideskriptor, der durch Öffnen oder Erstellen neu abgestimmt wurde, als Argument zum Lesen oder Schreiben.
  • Jeder UNIX-Prozess verfügt über 20 Dateideskriptoren und verfügt über die Nummern 0 bis 19, wurde jedoch von vielen Systemen auf 63 erweitert.
  • Die ersten drei sind bereits zu Beginn des Prozesses geöffnet. 0: Die Standardeingabe 1: Die Standardausgabe 2: Die Standardfehlerausgabe
  • Wenn der übergeordnete Prozess einen Prozess gabelt, erbt der untergeordnete Prozess die Dateideskriptoren des übergeordneten Prozesses
Mahendra Suthar
quelle
1

Ergänzung zu vor allem vereinfachten Antworten.
Wenn Sie mit Dateien im Bash-Skript arbeiten, ist es besser, den Dateideskriptor zu verwenden.
Zum Beispiel: -
Sie möchten von / in die Datei "test.txt" lesen und schreiben.
Verwenden Sie den Dateideskriptor wie unten gezeigt

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
quelle
-5

Dateideskriptoren sind die Deskriptoren einer Datei. Sie geben Links zu einer Datei. Mit ihrer Hilfe können wir eine Datei lesen, schreiben und öffnen.

Motimahal
quelle