Quelle serait une description plus simplifiée des descripteurs de fichiers par rapport à celle de Wikipedia? Pourquoi sont-ils nécessaires? Disons, prenons comme exemple les processus Shell et comment cela s’applique-t-il?
Une table de processus contient-elle plusieurs descripteurs de fichier? Si oui pourquoi?
En termes simples, lorsque vous ouvrez un fichier, le système d'exploitation crée une entrée pour représenter ce fichier et stocker les informations sur ce fichier ouvert. Donc, si 100 fichiers sont ouverts dans votre système d'exploitation, il y aura 100 entrées dans le système d'exploitation (quelque part dans le noyau). Ces entrées sont représentées par des entiers tels que (... 100, 101, 102 ...). Ce numéro d'entrée est le descripteur de fichier. Il s’agit donc d’un nombre entier représentant uniquement un fichier ouvert dans le système d’exploitation. Si votre processus ouvre 10 fichiers, votre table de processus comportera 10 entrées pour les descripteurs de fichier.
De même, lorsque vous ouvrez une socket réseau, celle-ci est également représentée par un entier et s'appelle Socket Descriptor. J'espère que tu comprends.
Un descripteur de fichier est un descripteur opaque utilisé dans l'interface entre l'utilisateur et l'espace noyau pour identifier les ressources de fichier/socket. Par conséquent, lorsque vous utilisez open()
ou socket()
(appels système pour l'interface avec le noyau), un descripteur de fichier, qui est un entier (il s'agit en fait d'un index dans la structure du processus), vous est attribué. ce n'est pas important). Par conséquent, si vous souhaitez vous connecter directement au noyau en utilisant les appels système à read()
, write()
, close()
etc., le descripteur que vous utilisez est un descripteur de fichier.
Il existe une couche d'abstraction superposée sur les appels système, qui est l'interface stdio
. Cela fournit plus de fonctionnalités/fonctionnalités que les appels système de base. Pour cette interface, le descripteur opaque que vous obtenez est un FILE*
, qui est renvoyé par l'appel fopen()
. Il existe de nombreuses fonctions qui utilisent l'interface stdio
fprintf()
, fscanf()
, fclose()
, qui sont là pour vous simplifier la vie. En C, stdin
, stdout
et stderr
sont FILE*
, qui sous UNIX correspondent respectivement aux descripteurs de fichier 0
, 1
et 2
.
Écoutez-le dans la bouche du cheval: APUE (Richard Stevens).
Pour le noyau, tous les fichiers ouverts sont référencés par des descripteurs de fichiers. Un descripteur de fichier est un nombre non négatif.
Lorsque nous ouvrons un fichier existant ou créons un nouveau fichier, le noyau renvoie un descripteur de fichier au processus. Le noyau conserve une table de tous les descripteurs de fichiers ouverts. , qui sont en cours d'utilisation. L'attribution de descripteurs de fichier est généralement séquentielle et ils sont attribués au fichier en tant que prochain descripteur de fichier libre à partir du pool de descripteurs de fichiers libres. Lorsque nous fermons le fichier, le descripteur de fichier est libéré et est disponible pour une affectation ultérieure.
Voir cette image pour plus de détails:
Lorsque nous voulons lire ou écrire un fichier, nous identifions le fichier avec le descripteur de fichier renvoyé par open () ou create () et utilisez-le comme argument pour read () ou write () .
C’est par convention que, les shells du système UNIX associent le descripteur de fichier 0 à une entrée standard d’un processus, le descripteur de fichier 1 à Sortie standard et descripteur de fichier 2 avec Erreur standard .
Le descripteur de fichier est compris entre 0 et OPEN_MAX. La valeur maximale du descripteur de fichier peut être obtenue avec ulimit -n
. Pour plus d'informations, consultez le 3ème chapitre du livre APUE.
Plus de points concernant File Descriptor
:
File Descriptors
(FD) sont des entiers non négatifs (0, 1, 2, ...)
qui sont associés aux fichiers ouverts.
0, 1, 2
sont standard FD qui correspond à STDIN_FILENO
, STDOUT_FILENO
et STDERR_FILENO
(défini dans unistd.h
) ouvert par défaut pour le compte de Shell au démarrage du programme.
Les FD sont alloués dans l'ordre séquentiel, c'est-à-dire la valeur entière non allouée la plus basse possible.
Les FD pour un processus particulier sont visibles dans /proc/$pid/fd
(sur les systèmes Unix).
En plus d'autres réponses, Unix considère tout comme un système de fichiers. Votre clavier est un fichier qui est lu uniquement du point de vue du noyau. L'écran est un fichier en écriture seule. De même, les dossiers, les périphériques d’entrée-sortie, etc. sont également considérés comme des fichiers. Chaque fois qu'un fichier est ouvert, par exemple, lorsque les pilotes de périphérique [pour les fichiers de périphérique] demandent un open (), ou qu'un processus ouvre un fichier utilisateur, le noyau alloue un descripteur de fichier, un entier spécifiant l'accès à ce fichier, en lecture seule. , écrivez seulement, etc. [pour référence: https://en.wikipedia.org/wiki/Everything_is_a_file ]
D'autres réponses ont ajouté des trucs géniaux. Je vais ajouter seulement mes 2 cents.
Selon Wikipedia, nous savons avec certitude: un descripteur de fichier est un entier non négatif. La chose la plus importante qui me manque est de dire:
Les descripteurs de fichier sont liés à un ID de processus.
Nous savons que les descripteurs de fichiers les plus connus sont 0, 1 et 2. 0 correspond à STDIN
, 1 à STDOUT
et 2 à STDERR
.
Disons, prenons l'exemple des processus Shell et comment cela s'applique-t-il?
Découvrez ce code
#>sleep 1000 &
[12] 14726
Nous avons créé un processus avec l'ID 14726 (PID). En utilisant le lsof -p 14726
, nous pouvons obtenir les choses comme ceci:
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 quatrième colonne FD et la colonne très suivante TYPE correspondent au descripteur de fichier et au type de descripteur de fichier.
Certaines des valeurs pour le FD peuvent être:
cwd – Current Working Directory
txt – Text file
mem – Memory mapped file
mmap – Memory mapped device
Mais le descripteur de fichier réel est sous:
NUMBER – Represent the actual file descriptor.
Le caractère après le nombre, à savoir "1u", représente le mode dans lequel le fichier est ouvert. r pour lire, w pour écrire, u pour lire et écrire.
TYPE spécifie le type du fichier. Certaines des valeurs de TYPE sont:
REG – Regular File
DIR – Directory
FIFO – First In First Out
Mais tous les descripteurs de fichiers sont CHR - Fichier spécial de caractères (ou fichier de périphérique de caractères)
Maintenant, nous pouvons identifier les descripteurs de fichier pour STDIN
, STDOUT
et STDERR
facile avec lsof -p PID
, ou nous pouvons voir la même chose si nous ls /proc/PID/fd
.
Notez également que la table de descripteur de fichier dont le noyau assure le suivi n’est pas la même que la table de fichiers ou la table inodes. Celles-ci sont séparées, comme l'expliquent d'autres réponses.
Vous pouvez vous demander où sont physiquement ces descripteurs de fichier et ce qui est stocké dans /dev/pts/6
par exemple
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
Eh bien, /dev/pts/6
ne vit que dans la mémoire. Ce ne sont pas des fichiers normaux, mais des fichiers de périphérique de caractères . Vous pouvez vérifier cela avec: ls -l /dev/pts/6
et ils commenceront par c
, dans mon cas crw--w----
.
Pour rappel, la plupart des systèmes d’exploitation Linux, comme les systèmes d’exploitation, définissent sept types de fichiers:
Descripteurs de fichier (FD):
$ ls mydir 2> errorsfile.txt
Le descripteur de fichier pour l'erreur type est 2.
S'il n'y a pas de répertoire nommé mydir, la sortie de la commande sera sauvegardée dans le fichier errorfile.txt
En utilisant "2>", nous redirigeons la sortie d'erreur vers un fichier nommé "errorfile.txt"
Ainsi, la sortie du programme n'est pas encombrée d'erreurs.
J'espère que vous avez eu votre réponse.
Tous les systèmes d'exploitation ont des processus (p) en cours d'exécution, par exemple p1, p2, p3 , etc. Chaque processus utilise généralement des fichiers en continu.
Chaque processus est constitué d'un arbre de processus (ou d'une table de processus, dans un autre phrasé).
Habituellement, les systèmes d'exploitation représentent chaque fichier de chaque processus par un nombre (c'est-à-dire, dans chaque arborescence/table de processus).
Le premier fichier utilisé dans le processus est fichier0 , le second est fichier1 , le troisième est fichier2 , etc.
n tel numéro est un descripteur de fichier.
Les descripteurs de fichier sont généralement des entiers (0, 1, 2 et non 0.5, 1.5, 2.5).
Étant donné que nous décrivons souvent les processus comme des "tables de processus", et étant donné que les tables ont des lignes (entrées), nous pouvons dire que la cellule de descripteur de fichier de chaque entrée utilise pour représenter l’entrée entière.
De la même manière, lorsque vous ouvrez une socket réseau, celle-ci comporte un descripteur de socket.
Dans certains systèmes d'exploitation, vous pouvez manquer de descripteurs de fichiers, mais ce cas est extrêmement rare et l'utilisateur moyen ne devrait pas s'en inquiéter.
Les descripteurs de fichier peuvent être globaux (le processus A commence par exemple par 0, et finit par tel par 1; le processus B par deux, et finit par par 3), etc., mais autant que je sache, généralement dans les systèmes d'exploitation modernes, fichier les descripteurs ne sont pas globaux, et sont en fait spécifiques à un processus (le processus A commence par, par exemple, 0 et se termine par, par 5, alors que le processus B commence par 0 et se termine par, par 10).
Ajout à des réponses surtout simplifiées.
Si vous travaillez avec des fichiers dans un script bash, il est préférable d’utiliser un descripteur de fichier.
Par exemple:-
Vous voulez lire et écrire à partir du fichier "test.txt".
Utilisez le descripteur de fichier comme indiqué ci-dessous
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