C'est une question de bas niveau, et je comprends que ce n'est peut-être pas le meilleur endroit où poser la question. Mais, il semblait plus approprié que tout autre site SE, alors voilà.
Je sais que sur le système de files Linux, certains files existent , par exemple: /usr/bin/bash
est un file existant. Cependant, pour autant que je le comprenne, certains n'existent pas en tant que tels et sont des files plus virtuels , par exemple: /dev/sda
, /proc/cpuinfo
, etc. Mes questions sont (elles sont deux mais aussi étroitement liés à des questions distinctes):
/dev/random
renvoie des données randoms, et une lecture de /dev/null
renvoie EOF
. Comment fonctionne-t-il datatables à lire à partir de ce file virtuel (et donc quoi faire quand / si datatables sont écrites dans le file virtuel) – existe-t-il une sorte de map avec des pointeurs pour séparer les commands en lecture / ou même pour le directory virtuel lui-même? Ainsi, une input pour /dev/null
pourrait simplement renvoyer un EOF
. Il y a donc fondamentalement deux types de choses différents ici:
/proc
et /sys
sont des exemples ici, tout comme les filesystems personnalisés FUSE comme sshfs
ou ifuse
. Il y a beaucoup plus de diversité dans ces domaines, car ils se réfèrent simplement à un système de files avec une sémantique qui est en quelque sorte «personnalisée». Ainsi, lorsque vous lisez un file sous /proc
, vous /proc
pas réellement à une donnée spécifique stockée par quelque chose d'autre l'écrivant plus tôt, comme dans un système de files normal. Vous faites essentiellement un appel du kernel, demandant des informations générées à la volée. Et ce code peut faire tout ce qu'il veut, car c'est juste une fonction qui implémente la sémantique de la read
. Ainsi, vous avez le comportement bizarre des files sous /proc
, comme par exemple prétendre être des liens symboliques quand ils ne sont pas vraiment. La key est que /dev
est en fait, généralement, l'un des premiers types. Il est normal dans les dissortingbutions modernes d'avoir /dev
comme quelque chose comme un tmpfs, mais dans les anciens systèmes, il était normal d'avoir un directory simple sur le disque, sans attributes spéciaux. La key est que les files sous /dev
sont des nœuds de périphériques, un type de file spécial similaire aux sockets FIFO ou Unix; un nœud de périphérique possède un numéro majeur et un numéro mineur. En les lisant ou en les écrivant, il appelle un pilote du kernel, comme lire ou écrire un FIFO, appelle le kernel pour qu'il tamponne votre sortie dans un tube. Ce pilote peut faire ce qu'il veut, mais il touche généralement le matériel d'une manière ou d'une autre, par exemple pour accéder à un disque dur ou jouer du son dans les haut-parleurs.
Pour répondre aux questions d'origine:
Il y a deux questions pertinentes pour savoir si le «file existe» ou non; il s'agit de savoir si le file de noeud du périphérique existe littéralement et si le code du kernel le sauvegarde. Le premier est résolu comme n'importe quoi sur un système de files normal. Les systèmes modernes utilisent udev
ou quelque chose comme ça pour surveiller les events matériels et créer et détruire automatiquement les nœuds de périphériques sous /dev
conséquence. Mais les systèmes plus anciens, ou les builds légers, peuvent simplement avoir tous leurs nœuds de périphériques littéralement sur le disque, créés à l'avance. Pendant ce time, lorsque vous lisez ces files, vous appelez le code du kernel qui est déterminé par les numéros de périphérique majeurs et mineurs; si ce n'est pas raisonnable (par exemple, vous essayez de lire un périphérique bloqué qui n'existe pas), vous obtiendrez simplement une sorte d'erreur d'E / S.
La façon dont il fonctionne sur quel code kernel appeler pour quel file de périphérique varie. Pour les filesystems virtuels comme /proc
, ils implémentent leurs propres fonctions de read
et d' write
; le kernel appelle simplement ce code en fonction du sharepoint assembly dans lequel il se trouve et l'implémentation du système de files prend soin du rest. Pour les files de périphérique, il est dissortingbué en fonction des numéros de périphérique majeurs et mineurs.
Voici une list de files de /dev/sda1
sur mon server Arch Linux presque à jour:
% ls -li /dev/sda1 1294 brw-rw---- 1 root disk 8, 1 Nov 9 13:26 /dev/sda1
Ainsi, l'input de directory dans /dev/
pour sda
a un numéro d'inode, 1294. C'est un vrai file sur le disque.
Regardez où la taille du file apparaît généralement. "8, 1" apparaît à la place. C'est un numéro de périphérique majeur et mineur. Notez également le 'b' dans les permissions de file.
Le file /usr/include/ext2fs/ext2_fs.h
contient ce (fragment) C struct:
/* * Structure of an inode on the disk */ struct ext2_inode { __u16 i_mode; /* File mode */
Cette structure nous montre la structure sur disque de l'inode d'un file. Beaucoup de choses intéressantes sont dans cette structure; jetez-y un long regard.
L'élément i_mode
de struct ext2_inode
a 16 bits, et il utilise seulement 9 pour l'user / groupe / autre, les permissions de lecture / écriture / exécution et 3 autres pour setuid, setgid et sticky. Il dispose de 4 bits pour différencier les types de files tels que «file ordinaire», «lien», «directory», «canal nommé», «socket de la famille Unix» et «périphérique de bloc».
Le kernel Linux peut suivre l'algorithm habituel de search d'annuaire, puis prendre une décision en fonction des permissions et des indicateurs de l'élément i_mode
. Pour 'b', bloquer les files de périphériques, il peut find les numéros de périphériques majeurs et mineurs et, traditionnellement, utiliser le numéro de périphérique principal pour searchr un pointeur vers une fonction kernel (un pilote de périphérique) traitant des disques. Le numéro d'appareil mineur s'utilise habituellement comme le numéro du périphérique de bus SCSI ou le numéro de périphérique EIDE ou quelque chose comme ça.
D'autres décisions concernant la gestion d'un file comme /proc/cpuinfo
sont sockets en fonction du type de système de files. Si vous faites un:
% mount | grep proc proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
vous pouvez voir que /proc
a le type de système de files "proc". La lecture à partir d'un file dans /proc
amène le kernel à faire quelque chose de différent en fonction du type de système de files, tout comme l'ouverture d'un file sur un système de files ReiserFS ou DOS entraînerait l'utilisation de différentes fonctions pour localiser les files et localiser datatables des files.
À la fin de la journée, ils sont tous des files pour Unix, c'est la beauté de l'abstraction.
La façon dont les files sont gérés par le kernel, c'est une histoire différente.
/ proc et de nos jours / dev et / run (aka / var / run) sont des filesystems virtuels en RAM. / proc est une interface / windows pour les variables et les structures du kernel.
Je vous recommand de lire le Linux Kernel http://tldp.org/LDP/tlk/tlk.html et les pilotes de périphériques Linux, troisième édition https://lwn.net/Kernel/LDD3/ .
J'ai également apprécié la design et la mise en œuvre du operating system FreeBSD http://www.amazon.com/Design-Implementation-FreeBSD-Operating-System/dp/0321968972/ref=sr_1_1
Jetez un oeil à la page pertinente qui se rapporte à votre question.
En plus des réponses de @ RuiFRibeiro et @ BruceEdiger, la distinction que vous faites n'est pas exactement la distinction faite par le kernel. En fait, vous avez différents types de files: des files réguliers, des directorys, des liens symboliques, des périphériques, des sockets (et j'en oublie toujours quelques-uns donc je n'essaierai pas de faire une list complète). Vous pouvez avoir l'information sur le type d'un file avec ls
: c'est le premier caractère sur la ligne. Par exemple:
$ls -la /dev/sda brw-rw---- 1 root disk 8, 0 17 nov. 08:29 /dev/sda
Le «b» au tout début indique que ce file est un périphérique de blocage. Un tiret, signifie un file régulier, 'l' un lien symbolique et ainsi de suite. Ces informations sont stockées dans les métadonnées du file et sont accessibles via l'appel système stat
par exemple, de sorte que le kernel peut lire différemment un file et un lien symbolique par exemple.
Ensuite, vous faites une autre distinction entre les "files réels" comme /bin/bash
et les "files virtuels" comme /proc/cpuinfo
mais ls
déclarent tous les deux comme des files réguliers, donc la différence est d'un autre type:
ls -la /proc/cpuinfo /bin/bash -rwxr-xr-x 1 root root 829792 24 août 10:58 /bin/bash -r--r--r-- 1 root wheel 0 20 nov. 16:50 /proc/cpuinfo
Ce qui se passe est qu'ils appartiennent à différents filesystems. /proc
est le sharepoint assembly d'un pseudo-système de files procfs
tandis que /bin/bash
trouve sur un système de files disque standard. Lorsque Linux ouvre un file (il le fait différemment selon le système de files), il remplit un file
structure de données qui a, entre autres attributes, une structure de plusieurs pointeurs de fonction qui décrivent comment utiliser ce file. Par conséquent, il peut implémenter des comportements distincts pour différents types de files.
Par exemple, ce sont les opérations annoncées par /proc/meminfo
:
static int meminfo_proc_open(struct inode *inode, struct file *file) { return single_open(file, meminfo_proc_show, NULL); } static const struct file_operations meminfo_proc_fops = { .open = meminfo_proc_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, };
Si vous regardez la définition de meminfo_proc_open
, vous pouvez voir que cette fonction remplit un tampon en memory avec les informations returnnées par la fonction meminfo_proc_show
, dont la tâche est de collecter des données sur l'utilisation de la memory. Cette information peut alors être lue normalement. Chaque fois que vous ouvrez le file, la fonction meminfo_proc_open
est appelée et les informations sur la memory sont actualisées.
Tous les files d'un système de files sont "réels" dans la mesure où ils autorisent les E / S de files. Lorsque vous ouvrez un file, le kernel crée un descripteur de file, qui est un object (au sens de la programmation orientée object) qui agit comme un file. Si vous lisez le file, le descripteur de file exécute sa méthode de lecture, qui à son tour requestra au système de files (sysfs, ext4, nfs, etc.) datatables du file. Les filesystems présentent une interface uniforme avec l'espace user et savent ce qu'il faut faire pour gérer les lectures et les écritures. Les filesystems requestnt à leur tour à d'autres couches de traiter leurs requests. Pour un file standard, par exemple un système de files ext4, il faut searchr des data structures du système de files (qui peuvent impliquer des lectures de disque) et éventuellement une lecture du disque (ou cache) pour copyr datatables dans le tampon de lecture. Pour un file dans dis sysfs, il suffit généralement de sprintf () s quelque chose à la memory tampon. Pour un nœud de développement de bloc, il requestra au pilote de disque de lire certains blocs et de les copyr dans le tampon (les numéros majeurs et mineurs indiquent au système de files à quel pilote faire les requêtes).