Pourquoi un progiciel fonctionne-t-il très bien même lorsqu'il est mis à niveau?
29
Supposons que j'exécute un logiciel, puis que j'exécute le gestionnaire de packages pour mettre à niveau le logiciel, je remarque que Linux n'interrompt pas le processus en cours pour la mise à niveau des packages - il fonctionne toujours correctement. Comment Linux fait-il cela?
La raison est qu'Unix ne verrouille pas un fichier exécutable pendant qu'il est exécuté ou même s'il aime Linux, ce verrou s'applique à l'inode, pas au nom de fichier. Cela signifie qu'un processus qui le garde ouvert accède aux mêmes (anciennes) données même après que le fichier a été supprimé (non lié en fait) et remplacé par un nouveau avec le même nom, ce qui est essentiellement ce que fait une mise à jour de package.
C'est l'une des principales différences entre Unix et Windows. Ce dernier ne peut pas mettre à jour un fichier verrouillé car il manque une couche entre les noms de fichier et les inodes, ce qui complique grandement la mise à jour ou même l'installation de certains packages car il nécessite généralement un redémarrage complet.
Pour clarifier, sous Linux, vous ne pouvez pas modifier un fichier exécutable pendant son exécution. Mais vous pouvez dissocier le fichier et le remplacer par un nouveau fichier du même nom.
cjm
Sous Linux, vous pouvez modifier un fichier exécutable pendant son exécution. Le résultat serait probablement imprévisible, sauf si vous savez vraiment ce que vous faites. Ajout du point "même nom" qui n'était pas explicitement indiqué.
jlliagre
4
@jlliagre À moins que je ne comprenne mal, vous ne pouvez pas autant que je sache: sprunge.us/egiR
Chris Down
2
Une chose intéressante à propos de NFTS - si vous effectuez un changement de nom à partir de la ligne de commande ou d'un autre programme, vous pouvez placer un fichier du même nom là-bas, et cela n'affectera pas les programmes qui ont le fichier d'origine ouvert. (la commande renommer dans l'explorateur ne fonctionne pas pour cela)
Steffan Donal
1
@cjm Vous avez raison sur la protection "fichier texte occupé" sous Linux, réponse mise à jour. Il n'y a pas une telle restriction sous Solaris avec laquelle je suis plus familier. Vous pouvez toujours modifier les bibliothèques partagées avec les deux systèmes d'exploitation.
jlliagre
18
Les exécutables sont généralement ouverts une fois, attachés à un descripteur de fichier et n'ont pas de descripteur de fichier à leur binaire rouvert pendant une seule période d'exécution. Par exemple, si vous exécutez bash, exec()ne crée généralement qu'un descripteur de fichier pour l'inode indiqué par /bin/bashune invocation unique.
Cela signifie souvent que pour les binaires simples qui n'essaient pas de se relire pendant l'exécution (en utilisant le chemin par lequel ils ont été invoqués), le contenu mis en cache reste valide en tant qu'inode pendant. Cela signifie qu'il existe essentiellement une réplique de la version précédente de l'exécutable.
Dans des cas plus complexes, cela peut entraîner des problèmes. Par exemple, un fichier de configuration peut être mis à niveau et relu par la suite, ou le programme peut se ré-exécuter via le chemin à partir duquel il a été exécuté. Il peut également y avoir des problèmes si les programmes sont interconnectés, et l'un est exécuté avant la mise à niveau, et l'autre après (éventuellement par le premier programme). Cela est également vrai pour certaines bibliothèques.
Pour les cas d'utilisation simples, cependant, la mise à niveau est sûre sans redémarrer le processus.
L'autre danger, même dans les cas simples, est que parce que l'application en cours utilise une copie mise en cache du binaire, jusqu'à ce que vous redémarriez manuellement l'application, elle exécute toujours l'ancienne version du code. Bien que cela ne devrait pas avoir d'importance la plupart du temps; si la mise à niveau comprenait des correctifs de sécurité, malgré l'installation du correctif, votre système est toujours vulnérable car l'ancienne version est toujours en cours d'exécution.
Dan Neely
1
J'ai bien peur que votre premier paragraphe soit inexact. Les noyaux Unix / Linux ne chargent pas les programmes exécutables à la fois mais la mémoire les mappe. Cela signifie que seules les pages réellement utilisées parviennent finalement à la RAM. C'est tout l'intérêt de la protection "Fichier texte occupé" sous Linux. Il n'y a aucune garantie qu'une partie d'un exécutable ne sera pas lue longtemps après son lancement. De plus, certaines pages ne seront jamais chargées pour des programmes suffisamment volumineux et cela est encore plus vrai pour les bibliothèques chargées dynamiquement. Par exemple, le bashbinaire représente environ 200 pages 4K, pas sûr qu'elles soient toutes utilisées dans une session moyenne.
jlliagre
@jlliagre Je parlais d'une ialloc()ing à une structure du noyau en lecture, pas du mappage mémoire des pages elles-mêmes. N'ai-je pas raison de penser que sur les systèmes de fichiers ext * modernes, l'inode est finalement cohérent dans le noyau (et à l'intérieur du sous-système VM)?
Chris Down
Il n'y a aucune garantie que certaines parties du contenu exécutable ne seront pas lues longtemps après son exécution, et il n'y a aucune garantie non plus que les mêmes pages ne seront pas relues après un certain temps pendant le temps d'exécution.
jlliagre
@jlliagre C'est vrai, mais ce n'est pas ce que je voulais dire. J'ai peut-être un peu haché mes mots dans ma réponse, je vais essayer de clarifier ce que je voulais dire.
Les exécutables sont généralement ouverts une fois, attachés à un descripteur de fichier et n'ont pas de descripteur de fichier à leur binaire rouvert pendant une seule période d'exécution. Par exemple, si vous exécutez
bash
,exec()
ne crée généralement qu'un descripteur de fichier pour l'inode indiqué par/bin/bash
une invocation unique.Cela signifie souvent que pour les binaires simples qui n'essaient pas de se relire pendant l'exécution (en utilisant le chemin par lequel ils ont été invoqués), le contenu mis en cache reste valide en tant qu'inode pendant. Cela signifie qu'il existe essentiellement une réplique de la version précédente de l'exécutable.
Dans des cas plus complexes, cela peut entraîner des problèmes. Par exemple, un fichier de configuration peut être mis à niveau et relu par la suite, ou le programme peut se ré-exécuter via le chemin à partir duquel il a été exécuté. Il peut également y avoir des problèmes si les programmes sont interconnectés, et l'un est exécuté avant la mise à niveau, et l'autre après (éventuellement par le premier programme). Cela est également vrai pour certaines bibliothèques.
Pour les cas d'utilisation simples, cependant, la mise à niveau est sûre sans redémarrer le processus.
la source
bash
binaire représente environ 200 pages 4K, pas sûr qu'elles soient toutes utilisées dans une session moyenne.ialloc()
ing à une structure du noyau en lecture, pas du mappage mémoire des pages elles-mêmes. N'ai-je pas raison de penser que sur les systèmes de fichiers ext * modernes, l'inode est finalement cohérent dans le noyau (et à l'intérieur du sous-système VM)?