Comment savoir si un fichier est mappé en mémoire?

8

Je suis confus au sujet des fichiers mappés en mémoire, j'ai donc quelques questions que je serais très heureux si vous pouviez m'aider.

  1. Disons que je navigue vers un répertoire de mon système de fichiers et qu'il y a un fichier dans ce répertoire. Est-il possible que ce fichier pointe vers une région de la mémoire principale, au lieu de pointer vers une région du disque?
  2. Si cela est possible, est-ce ce que nous appelons un «fichier mappé en mémoire»?
  3. Quelle serait la signification du déplacement d'un tel fichier dans le système de fichiers (c'est-à-dire, un mvtel fichier d'un répertoire à un autre)? Ce que je comprends, étant donné que le fichier est mappé en mémoire, le ou les processus interagissant avec le fichier écrivent toujours dans une région prédéfinie de la mémoire principale, et lorsque nous ouvrons ce fichier (par exemple en utilisant vim), nous lisons cette région de principal mémoire (donc, aucun disque n'est impliqué). Par conséquent, peu importe où nous déplaçons le fichier, il fonctionnera toujours correctement, non? Si oui, le déplacement du fichier dans le système de fichiers a-t-il une signification?
  4. Existe-t-il une commande qui indiquerait si un fichier est mappé en mémoire?
  5. Enfin, si j'ouvre un fichier mappé en mémoire avec vim, y apporte des modifications et l'enregistre et le ferme vim, que se passera-t-il? Mes modifications seront-elles simplement écrites dans la mémoire principale? Si tel est le cas, les autres processus qui utilisent ce fichier verront-ils les modifications que je viens d'apporter? D'après mon expérience, les autres processus n'ont pas vu les modifications que j'ai apportées au fichier lorsque j'ai apporté des modifications au fichier avec vim. Quelle est la raison pour ça?
Utku
la source
12
Cela me rappelle que quelqu'un demande comment savoir si un fichier est un lien dur.
Dmitry Grigoryev
3
@DmitryGrigoryev C'est assez drôle, en fait, mais tout le monde apprend :)
cat

Réponses:

24

Les fichiers mappés en mémoire fonctionnent dans l'autre sens. Le mappage de la mémoire n'est pas une propriété du fichier, mais un moyen d'accéder au fichier: un processus peut mapper le contenu d'un fichier (ou un sous-ensemble de celui-ci) dans son espace d'adressage. Cela facilite la lecture et l'écriture dans le fichier; cela implique simplement de lire et d'écrire en mémoire. Le fichier lui-même, sur disque, est identique à tout autre fichier.

Pour configurer cela, les processus utilisent la mmapfonction. Cela peut également être utilisé à d'autres fins, comme le partage de mémoire entre les processus.

Stephen Kitt
la source
14
@Utku Cela n'a rien à voir avec les fichiers mappés en mémoire.
Satō Katsura
12
Si vous n'avez pas arrêté le serveur MySQL, c'est un comportement normal: le serveur a un descripteur de fichier ouvert sur le fichier, et cela reste valable même avec mv.
Stephen Kitt
11
Le descripteur de fichier pointe (éventuellement) vers des inodes dans le système de fichiers; c'est là que le fichier réside vraiment. Les entrées de répertoire pointent également vers ces inodes, et mvchangent simplement les entrées de répertoire, pas les inodes (quand il déplace des fichiers sur le même système de fichiers).
Stephen Kitt
1
Votre description est une simplification utile, mais juste pour plus de précision: les mappages de mémoire ne sont techniquement pas la même chose que les descripteurs de fichiers, mais ils fonctionnent de la même manière (par référence à l'inode, pas au nom de fichier). open (), mmap (), close () ne laisse aucun FD, juste un mappage, qui apparaîtra avec lsof. Il ne disparaît que lorsque le processus appelle munmap (), ou quitte (ou remplace le mappage par un autre en utilisant mmap (MAP_FIXED) ...)
Peter Cordes
3
@Utku Vous n'avez pas réellement déplacé le fichier. Vous venez de créer une nouvelle entrée de répertoire qui fait référence au même fichier, puis vous avez supprimé l'ancien. Le changement de dénomination n'a aucun effet sur un processus qui a déjà ouvert le fichier.
David Schwartz
11

Un fichier mappé en mémoire n'est pas (nécessairement) sauvegardé par la mémoire. Il peut parfaitement vivre sur un disque. En fait, l'emplacement d'un fichier n'est pas une propriété du fichier lui-même mais du système de fichiers dans lequel il réside.

Le mappage d'un fichier en mémoire est une opération qu'un processus peut effectuer pour charger une partie du fichier en mémoire. Le résultat ressemble à une région de mémoire normale, sauf que lorsque le processus lit ou écrit dans cette région, il lit et écrit dans le fichier. Si vous ouvrez un fichier, mappez-le en mémoire, écrivez-le et enregistrez-le, la modification se fera sur le fichier, sur le disque (s'il vit sur un disque, bien sûr).

Ceci peut être utilisé par exemple lorsque vous savez que vous avez beaucoup d'accès à faire sur un fichier, qui ne va pas être séquentielle, être la cause , il peut être plus facile et plus efficace de faire des lectures et écritures en mémoire plutôt que d' effectuer read, write, et les llseekappels système. Le seul problème avec cette méthode est que vous ne pouvez pas vraiment l'utiliser si le fichier doit être lu ou écrit par plusieurs processus simultanément. Les résultats seraient imprévisibles.

Je ne connais aucune commande qui puisse vous dire si un fichier est actuellement mappé. Vous pouvez cependant inspecter les mappages d'un processus dans /proc/<pid>/maps(si votre système en dispose).

Pour répondre à votre deuxième question, lorsque vous ouvrez un fichier, même si vous le déplacez dans le système de fichiers, les processus qui l'ont ouvert peuvent toujours l'utiliser. Ce qui se passe, c'est qu'un fichier ne dépend pas de ses entrées dans les systèmes de fichiers. Tant qu'un fichier est ouvert, vous disposez d'un "descripteur", un descripteur de fichier, qui vous permet de lire et d'écrire dessus, même si son chemin dans le système de fichiers change. Un fichier ne disparaît que s'il n'a aucune entrée dans le système de fichiers et qu'aucun processus ne contient de descripteur de fichier.

lgeorget
la source
Ainsi, lorsque nous déplaçons un fichier, la valeur du descripteur de fichier ne change pas. Il existe un mappage de descripteur chemin vers fichier et seule la partie chemin de ce mappage change. Est-ce correct?
Utku
1
Dans un certain sens oui, mais je ne suis pas sûr de vous comprendre alors laissez-moi le reformuler. Fondamentalement, "un fichier", c'est trois choses. Une entrée de répertoire est un chemin d'accès dans le système de fichiers. Un inode est le contenu d'un fichier. Et un descripteur de fichier représente un fichier ouvert. Les entrées de répertoire et les descripteurs de fichiers contiennent un pointeur sur leur inode de support. Lorsque vous ouvrez un fichier, vous passez l'entrée de répertoire et le noyau vous renvoie un descripteur de fichier. Ainsi, même si l'entrée de répertoire d'origine change, le descripteur de fichier pointe toujours vers le même inode et vous pouvez accéder au fichier.
lgeorget
1
Vous pouvez cependant inspecter les mappages d'un processus dans /proc/<pid>/maps. - Pourvu que ce processus vive sur un système qui a /procpour commencer. OpenBSD ne le fait pas et FreeBSD le supprime progressivement. De plus, FreeBSD a /proc/<pid>/mapau lieu de /proc/<pid>/maps.
Satō Katsura
@SatoKatsura Merci pour la précision. Je n'ai qu'une machine Linux à portée de main, alors j'avais pensé parler de mon cas et laisser les gens parler du leur ... N'hésitez pas à modifier la réponse si vous avez des choses à corriger / ajouter ici.
lgeorget
Puisque vous demandez: vous avez supposé que l'OP comprend réellement ce qu'il demande et avez expliqué en détail ce que sont les fichiers mappés en mémoire. Je ne pense pas que tu lui aies rendu service. OMI votre premier commentaire était au- dessus beaucoup plus pertinent à ce que l'OP a été effectivement demandé alors votre réponse. FWIW.
Satō Katsura
9

Q4: Existe-t-il une commande qui indiquerait si un fichier est mappé en mémoire?

La lsofcommande vous montrera tous les fichiers actuellement utilisés par le système. La colonne "FD" contiendra "mem" si le fichier est mappé en mémoire. Vous pouvez donc récupérer la sortie de cette commande pour le nom de fichier qui vous intéresse.

Wossname
la source
3
Ou utilisezlsof -ad mem /path/to/file
Stéphane Chazelas
5
Ou plutôt, lsof -ad mem,txt /path/to/filecomme les fichiers en cours d'exécution ont également des parties d'entre eux mmappées dans l'espace d'adressage du processus mais apparaissent comme txtdans la lsofsortie.
Stéphane Chazelas
7

Vous semblez confondre le mappage de la mémoire avec des fichiers dans des systèmes de fichiers résidant en mémoire, ainsi que d'autres concepts tels que la façon dont les processus conservent l'accès aux fichiers même lorsqu'ils sont déplacés.

Je vais aller question par question pour voir si je peux clarifier les choses.

  1. Disons que je navigue vers un répertoire de mon système de fichiers et qu'il y a un fichier dans ce répertoire. Est-il possible que ce fichier pointe vers une région de la mémoire principale, au lieu de pointer vers une région du disque?

Il pointe vers la mémoire principale si elle se trouve sur un système de fichiers résidant en mémoire, comme procfs qui est généralement monté sur / proc, ou sysfs qui est sur / sys, ou tmpfs qui est parfois sur / tmp.

  1. Si cela est possible, est-ce ce que nous appelons un «fichier mappé en mémoire»?

Non. Comme l'a dit stephen-kitt, "mappage de mémoire" fait référence à un moyen d'accéder à un fichier en le "mappant" sur la mémoire principale et en y travaillant plutôt que de lire et d'écrire des morceaux à la fois via des fonctions comme read () et écrire().

  1. Quelle serait la signification de déplacer un tel fichier dans le système de fichiers (c'est-à-dire de déplacer un tel fichier d'un répertoire vers un autre)? Ce que je comprends, c'est que le fichier étant mappé en mémoire, le ou les processus interagissant avec le fichier écrivent toujours dans une région prédéfinie de la mémoire principale et lorsque nous ouvrons ce fichier (par exemple à l'aide de vim), nous lisons cette région de mémoire principale (donc, aucun disque n'est impliqué). Par conséquent, peu importe où nous déplaçons le fichier, il fonctionnera toujours correctement, n'est-ce pas? Si oui, le déplacement du fichier dans le système de fichiers a-t-il une signification?

Si vous le déplacez dans le même système de fichiers, vous ne faites que déplacer une référence, un inode d'un répertoire à un autre. S'il y a des programmes qui avaient déjà ouvert ce fichier, ils accéderont toujours au même fichier car ils ont déjà l'inode à portée de main via un descripteur de fichier. C'est ce qui s'est produit avec le fichier nom_table.idb que vous avez mentionné dans un commentaire.

  1. Existe-t-il une commande qui indiquerait si un fichier est mappé en mémoire?

Wossname a déjà répondu à cette question pour les fichiers mappés en mémoire. lsofvous indiquera quels processus ont le fichier mappé en mémoire.

Pour savoir si un fichier se trouve dans un système de fichiers résidant en mémoire, vous pouvez utiliser dfou mountpour répertorier les systèmes de fichiers et leurs points de montage. Il vous suffit de savoir quels types de systèmes de fichiers résident en mémoire en les recherchant (par exemple dans wikipedia).

  1. Enfin, si j'ouvre un fichier mappé en mémoire avec vim, y apporte des modifications et que j'enregistre et ferme vim, que se passera-t-il? Mes modifications seront-elles simplement écrites dans la mémoire principale? Si tel est le cas, les autres processus qui utilisent ce fichier verront-ils les modifications que je viens d'apporter? D'après mon expérience, les autres processus n'ont pas vu les modifications que j'ai apportées au fichier lorsque j'ai apporté des modifications au fichier avec vim. Quelle est la raison pour ça?

Personnellement, je n'ai pas utilisé la mmapfonction dans un programme C, mais si je comprends bien le survol man mmapet info mmap, il n'y a aucune magie impliquée dans le maintien de la représentation en mémoire en synchronisation. Dans sa forme de base, l'appel de mmap copie le contenu du fichier en mémoire et msyncest utilisé pour le réécrire de la mémoire sur le disque. Si le fichier sur disque change, rien n'est en place pour le détecter et modifier automatiquement la représentation en mémoire dans tous les processus qui l'ont mappé.

EDIT: Il s'avère que mmap () essaie en fait de garder la représentation en mémoire synchronisée dans certaines conditions. Si la carte est uniquement lue, elle sera synchronisée même lorsque d'autres processus écrivent dans le fichier. S'il est écrit dans (en l'attribuant à la région de mémoire), ce qui se passe dépend du drapeau MAP_SHARED ou MAP_PRIVATE apparemment obligatoire fourni à mmap (). Si MAP_PRIVATE est fourni, la carte se dérobe à partir de la représentation sur disque et cesse d'être synchronisée jusqu'à ce que vous utilisiez msync (). Si MAP_SHARED est fourni, les mises à jour sont rendues visibles aux autres processus qui ont le fichier mappé, ainsi que (bien que cela ne soit pas nécessairement immédiat) la représentation sur disque.

Je viens d'ouvrir vim sur un fichier existant eet d' exécuter la commande :w, tout en ayant inotifywait -m .exécuté dans un autre terminal. Parmi quelques morceaux étranges, c'est la partie importante dont je suis sorti inotifywait.

./ MOVED_FROM e
./ MOVED_TO e~
./ CREATE e
./ OPEN e
./ MODIFY e
./ CLOSE_WRITE,CLOSE e
./ ATTRIB e
./ ATTRIB e
./ DELETE e~

Vim crée un nouveau fichier et supprime l'ancien. Pourquoi cela fait-il au lieu de modifier le fichier est hors de portée de cette question, mais le fait est qu'il s'agit d'un nouveau fichier et donc d'un nouvel inode.

Maintenant, qu'entendez-vous par d'autres processus utilisant ce fichier? Si vous voulez dire les processus qui ont ouvert le fichier pendant que vous le faites, non, ils ne verront pas les modifications. En effet, bien qu'ils aient ouvert un fichier avec le même chemin d'accès, ils ne sont pas le même fichier. Si vous voulez dire les processus qui peuvent ouvrir le fichier après cela, alors oui, ils verront les changements. Ils ouvriront le nouveau fichier que vous avez créé.

Il est important de noter que même si les programmes peuvent sembler avoir un fichier ouvert sur l'interface utilisateur, cela ne signifie pas nécessairement qu'ils gardent le fichier ouvert dans le processus. Vim en est un exemple, comme illustré ci-dessus.

JoL
la source
3
" Si le fichier sur disque change, il n'y a rien en place pour le détecter et modifier automatiquement la représentation en mémoire dans tous les processus qui l'ont mappé. " Qu'est-ce qui changerait le système de fichiers sur disque derrière le mappage de page du système d'exploitation? système? Imaginez-vous un accès brut au périphérique de bloc ou à un périphérique de bloc partagé via iSCSI ou quelque chose?
David Schwartz
@ david-schwartz Non. J'imagine deux processus ayant un fichier open () 'ed. Le processus 1 utilise mmap () pour copier / mapper le contenu du fichier en mémoire. Ensuite, le processus 2 utilise write () (et éventuellement fsync ()) pour modifier le contenu du disque. À l'heure actuelle, le contenu du fichier que le processus 1 a en mémoire ne reflète pas les modifications apportées par le processus 2, n'est-ce pas?
JoL
Non bien sûr que non. Le but de la writefonction est de modifier les données du fichier. Cela peut signifier ou non changer le contenu du disque, mais quoi que cela implique, c'est la responsabilité du système de fichiers de bien faire les choses. Dans ce cas, cela impliquerait de modifier la page de mémoire mappée et de la marquer comme sale.
David Schwartz
@ david-schwartz J'ai expérimenté mmap (), et vous avez raison. Dans le scénario que j'ai présenté dans mon commentaire précédent, le contenu que le processus 1 avait en mémoire (dans la carte) reflétait réellement les changements, sauf si le processus 1 avait écrit dans la mémoire dans le mappage au préalable. Cela était vrai même lorsque le processus de changement 1 a été effectué à un emplacement différent du changement effectué par le processus 2. J'ai mis à jour la réponse en rayant ce qui est incorrect et en ajoutant ce que j'ai trouvé.
JoL
1
@ david-schwartz Désolé, je ne voulais pas laisser entendre que mmap s'est comporté différemment de ce que la documentation spécifiait, mais oui, je pense avoir rendu la réponse trop confuse. Je pense qu'il est toujours dans la portée, mais la question, "les autres processus qui utilisent ce fichier verront-ils les changements que je viens d'apporter?", Semble être trop large. Il y a trop de "ça dépend". Parce que le besoin du PO semble être purement autodidacte, j'ai essayé de donner une réponse précise et de couvrir autant de terrain que possible, mais j'aurais peut-être exagéré. Cependant, je suis toujours content de l'avoir fait, car j'ai aussi appris un peu.
JoL