Quand le fichier mmap (2) sera-t-il mis à jour? (3)

La dernière fois décrit deux types de méthodes de détection pour écrire dans la zone mMap, et trois types en détail (1a méthode de balayage de table de page, 1b). Méthode de numérisation de page physique, méthode de capture de 2 erreurs d'écriture) a été prévue. La dernière fois a en fait examiné le code source de Linux et NetBSD et a confirmé que les deux avaient adopté la méthode de capture des erreurs d'écriture. Dans cet article, nous examinerons deux autres systèmes d'exploitation, macOS et Solaris.

Pour macOS

macOS a été développé sur la base de NeXTSTEP (OpenSTEP), qui a été construit sur Mach 2.5, le micro-noyau de la CMU. Dans le micro-noyau, seules les fonctions minimales nécessaires sont implémentées dans le noyau, et des fonctions telles que la pile réseau, le système de fichiers et la gestion des processus sont implémentées sur un serveur (sous-système) qui s'exécute dans l'espace utilisateur. Cependant, un micro-noyau pur a souvent des problèmes de performances en raison de la fréquence élevée de commutation d'espace virtuel et de commutation de contexte, et les fonctions de sous-système sont souvent implémentées dans l'espace noyau. C'est ce qu'on appelle un noyau hybride (Windows est également classé comme un noyau hybride). Mach contient une grande quantité de code dérivé de 4.3BSD afin d'assurer la compatibilité avec 4.3BSD, qui était la norme à l'époque, et c'est un binaire unique qui s'exécute dans le même espace d'adressage que la partie micro-noyau. Était là. Autrement dit, il est classé comme un noyau hybride. Pour macOS, le noyau NeXT STEP, qui était Mach 2.5 + 4.3BSD, a été mis à jour vers le microkernel + FreeBSD de OSF / 1. Semble être. Les restes d'OSF / 1 apparaissent dans le nom de répertoire osfmk où la partie Mach de l'arborescence source est stockée. Les commandes Unix, etc. semblent également être basées sur FreeBSD.

L'ensemble de macOS n'est pas OSS, mais les parties dérivées de Mach / FreeBSD incluant le noyau (XNU) sont OSS sous le nom de Darwin. Il y a un [miroir] sur github (https://github.com/apple/darwin-xnu/), donc je vais y faire référence, mais comme le système de fichiers (APFS, HFS +) n'est pas inclus, il y a une sensation de démangeaisons.

J'ai mentionné que l'ancien système de mémoire virtuelle de NetBSD était basé sur Mach. UVM est également conçu sous l'influence du système de mémoire virtuelle Mach et présente de nombreuses similitudes avec le système de mémoire virtuelle XNU. Par exemple, le bit D est référencé par pmap_is_modified () comme NetBSD, et pmap_clear_modify () fonctionne de la même manière que NetBSD. De plus, il existe des interfaces telles que pmap_get_refmod () et pmap_clear_refmod () qui opèrent un bit et un bit D à la fois. Manipuler A bit et D bit en même temps signifie que contrairement à Linux et NetBSD, il recherche les pages sales en scannant la table des pages. Nous allons jeter un coup d'oeil.

Tableau des pages de numérisation

Le système de mémoire virtuelle de XNU semble se trouver dans un répertoire appelé osfmk / vm. La partie Mach est stockée dans un répertoire appelé osfmk, et la partie sous-système BSD est stockée dans un répertoire appelé bsd. [Bsd / vm](https://github.com/apple/darwin-xnu/tree/xnu-4903.221.2/bsd/vm Il existe également un répertoire appelé). bsd / vm implémente les parties dépendant du sous-système BSD telles que le pager vnode (équivalent au pager vnode de NetBSD).

En regardant la structure de données d'osfmk / vm, il existe des structures telles que struct vm_map, struct vm_map_entry, struct vm_page, etc. comme on le voit dans NetBSD, et vm_page est connecté à la liste par listq, pageq, etc. Fais-moi sentir ça.

Si vous effectuez un grep avec pmap_is_modified, pmap_clear_modify, pmap_get_refmod, pmap_clear_refmod, etc., vm_pageout.c ou Il semble être par ici parce qu'il est pris autour de .c. Cependant, c'est assez difficile à comprendre car il y a des blocs incroyablement longs et le nombre d'états (drapeau de la structure vm_page) est grand.

Il semble que ce soit l'une des caractéristiques qu'il existe de nombreuses files d'attente (listes) connectées via pageq. Fondamentalement, il semble déplacer les pages et changer l'ordre entre les listes actives / inactives / libres, mais chaque liste est divisée en plusieurs parties.

En le divisant en plusieurs listes de cette manière, il semble que le timing et la fréquence des scans puissent être finement contrôlés en fonction de l'état d'utilisation de la page.

L'analyse de chaque liste d'actifs / inactifs est Contexte après l'initialisation du noyau Il semble que ce sera fait tel quel. Le corps principal est une fonction longue avec près de 1500 lignes appelée vm_pageout_scan (). y a-t-il. Dans ce (par exemple, par ici), à la fois un bit et un bit D En même temps, si le bit D est défini, la page est sale.

		if (m->vmp_reference == FALSE && m->vmp_pmapped == TRUE) {
		        refmod_state = pmap_get_refmod(VM_PAGE_GET_PHYS_PAGE(m));

		        if (refmod_state & VM_MEM_REFERENCED)
			        m->vmp_reference = TRUE;
		        if (refmod_state & VM_MEM_MODIFIED) {
				SET_PAGE_DIRTY(m, FALSE);
			}
		}

Vous pouvez également chasser approximativement vm_fault () pour gérer les défauts de page. , Il semble qu'il n'y ait qu'une erreur (SEGV etc.) ou Copie en écriture au moment de l'erreur d'écriture.

D'après ce qui précède, il a été constaté que macOS semble utiliser une méthode de numérisation de page physique qui détecte le sale en inspectant D bit en même temps que l'inspection A bit dans le tableau des pages.

Pour OpenIndiana

En parlant de SunOS (Solaris: à proprement parler, la portée de SunOS et de Solaris semble être différente, mais je me fiche des détails), pendant un certain temps, c'était Unix, et c'était un système d'exploitation qui continuait d'influencer tous les OS basés sur Unix. .. Je pense que Linux visait SunOS jusqu'à environ 2,6. Dans ce domaine également, SunOS 4 a été le premier à intégrer le cache de pages utilisé pour mMap (2) et le cache tampon utilisé pour read (2) / write (2), par exemple.

Le SunOS a déjà publié le code source sous le nom d'OpenSolaris vers 5.10 (Solaris 10). La licence était CDDL, et bien qu'elle ne soit pas compatible avec la GPL, c'était OSS. À cette époque, le produit Solaris semblait également être basé sur OpenSolaris, mais lorsque Sun a été racheté par Oracle, le projet OpenSolaris dirigé par Sun (Oracle) a pris fin.

OpenIndiana, qui est dérivé de la dernière version d'OpenSolaris, est toujours en cours de développement, je voudrais donc étudier cela. De la partie illumos-gate qui inclut le noyau, la dernière version OpenIndiana Hipster 2020.04 Reportez-vous à commit correspondant à / openindiana-hipster-2020-04-is-here /). Le noyau se trouve dans usr / src / uts. Système de partage de temps Unix. La partie dépendante de x86 est uts / i86pc, et la partie indépendante de l'architecture est [uts / common](https //github.com/illumos/illumos-gate/tree/45de8795bcb0e4c49743f37edfdd2c89d5a7863b/usr/src/uts/common).

Tableau des pages de numérisation

Parmi les systèmes de mémoire virtuelle, la partie dépendante du modèle semble être la gestion HAT (Hardware Address Translation). Pour x86, accédez à uts / i86pc / vm / hat_i86.c y a-t-il. Il est très similaire à pmap, comme hat_t (struct hat) correspondant à chaque espace virtuel. Lire en diagonale à l'aide de PT_MOD une clé correspondant au bit PTE D comme bit PTE D Ensuite, nous pouvons voir ce qui suit.

hat_pagesync () prend une page struct (correspondant à une page physique: donc plusieurs PTE) et un drapeau bitmap comme arguments, et A bit, D bit, R / W bit d'un PTE qui fait référence à une page physique. Se reflète dans p_nrm de la page struct. En tant que drapeau

Prenez une image bitmap de. Je ne suis pas sûr de ce que signifie HAT_SYNC_STOP_ON_SHARED, mais je pense que cela donne un traitement préférentiel aux pages partagées par de nombreux espaces virtuels.

/*
 * get hw stats from hardware into page struct and reset hw stats
 * returns attributes of page
 * Flags for hat_pagesync, hat_getstat, hat_sync
 *
 * define	HAT_SYNC_ZERORM		0x01
 *
 * Additional flags for hat_pagesync
 *
 * define	HAT_SYNC_STOPON_REF	0x02
 * define	HAT_SYNC_STOPON_MOD	0x04
 * define	HAT_SYNC_STOPON_RM	0x06
 * define	HAT_SYNC_STOPON_SHARED	0x08
 */

Dans cet esprit, regardez le code qui scanne la table des pages. La partie indépendante du modèle du système de mémoire virtuelle se trouve dans uts / common / vm. Le code pour analyser la table des pages est en quelque sorte dans uts / common / os y a-t-il. Oh, pour une raison quelconque, il a le même nom de fichier que macOS. En fait, également sur FreeBSD [également sur NetBSD] avant la conversion UVM (http: //cvsweb.netbsd) .org / bsdweb.cgi / src / sys / vm / Attic / vm_pageout.c), donc cela pourrait être le cas (notez que macOS, FreeBSD et vm_pageout.c de NetBSD sont clairement enracinés).

OpenIndiana, ou source Solaris, contient de nombreux commentaires et est facile à lire. Le remplacement de la page est pageout_scanner (), qui est à usage exclusif. Il s'exécute dans le thread noyau de. Il semble implémenter l'algorithme Clock, mais contrairement aux autres systèmes d'exploitation que j'ai vus jusqu'à présent, il n'a pas de liste inactive, il semble utiliser une seule liste. L'aiguille signifie les aiguilles d'une horloge, et on a l'impression que les deux aiguilles, la main avant et la main arrière, suivent la liste des pages physiques (pages structurées) à intervalles réguliers (pages étendues).

page de vérification () semble être le point. Fondamentalement, fronthand [efface le bit D, un peu](https://github.com/illumos//illumos-gate/blob/45de8795bcb0e4c49743f37edfdd2c89d5a7863b/usr/src/uts/common/os/vm_pageout.c # L1010), allez après [vérifications un peu du revers](https://github.com/illumos//illumos-gate/blob/45de8795bcb0e4c49743f37edfdd2c89d5a7863b/usr/src/uts/common/os/vm_pageout.c# L1012) Ça y ressemble.

	/*
	 * Turn off REF and MOD bits with the front hand.
	 * The back hand examines the REF bit and always considers
	 * SHARED pages as referenced.
	 */
	if (whichhand == FRONT)
		pagesync_flag = HAT_SYNC_ZERORM;
	else
 		pagesync_flag = HAT_SYNC_DONTZERO | HAT_SYNC_STOPON_REF |
		    HAT_SYNC_STOPON_SHARED;

	ppattr = hat_pagesync(pp, pagesync_flag);

Et quand A bit est défini Revenir en arrière et lorsque le bit D est défini , Queue_io_request () [appel](https: //github.com/illumos//illumos-gate/blob/45de8795bcb0e4c49743f37edfdd2c89d5a7863b/usr/src/uts/common/os/vm_pageout.c#L1088), demandez l'exportation. Si aucun n'est défini, Annuler le mappage de la page Ouvrir.

D'après ce qui précède, on peut voir qu'OpenIndiana, ou Solaris à un certain moment, utilise une méthode de numérisation de page physique.

Pour 4.4BSD

En y regardant jusqu'à présent, j'ai vu que NetBSD et macOS, qui semblent avoir les mêmes racines, ont des méthodes différentes, et que Solaris, qui était la norme jusqu'à un certain temps, et Linux et NetBSD sont différents, quand ai-je changé la méthode? Êtes-vous venu le prendre ou vous êtes-vous soucié de l'histoire?

Si vous utilisez Unix depuis longtemps, vous vous souvenez peut-être qu'il y avait un démon appelé update (8) qui émettait un appel système appelé sync (2) une fois toutes les 30 secondes. L'écriture par write (2) etc. n'était pas automatiquement écrite par le noyau, et j'ai dû lancer fsync (2) etc. ou attendre que update (8) écrive après jusqu'à 30 secondes. Peut-être que le fichier mmap (2) était le même.

Par exemple, le code source de 4.4BSD, un ancêtre commun de NetBSD et macOS (macOS est l'un des ancêtres), peut être consulté sur le Web (https://minnie.tuhs.org/cgi-bin/utree). .pl? fichier = 4.4BSD / usr / src). vm_pageout.c, qui analysait de nombreuses listes actives / inactives sur macOS, est [si simple] sur 4.4BSD (https://minnie.tuhs.org/cgi-bin/utree.pl?file=4.4BSD /usr/src/sys/vm/vm_pageout.c). Je n'ai pas vu le bit D ici. De plus, Page Fault Code est une copie pour erreur d'écriture. -écrire simplement sur-écrire Au contraire, il est défini ici sync (2) Ainsi, seul le cache de tampon est vidé (même si le cache de page et le cache de tampon n'ont pas été intégrés à ce moment), et le cache de page utilisé par mMap n'est pas touché.

Il semble que le cache de page n'est vidé que lorsque msync (2) est émis et lorsque munmap (2) ou l'arrêt du processus. Dans le cas de NetBSD, sync (2) a commencé à vider le cache de page depuis février 1997. Il est.

Après cela, je n'ai fait que courir après cela, mais même lorsque la machine virtuelle Mach a été effacée [quand UVM a été introduit](https: / /github.com/NetBSD/src/commit/8f7ee94e136f377ecd00e43bc146adecc505c8ea) a la même apparence. Apparemment, lorsque le cache tampon et le cache de page sont intégrés Il semble qu'il soit venu attraper l'erreur d'écriture.

FreeBSD a perdu son historique pré-2.0-RELEASE en raison de problèmes juridiques. Il semble que 2.0 a déjà détecté l'erreur d'écriture et l'a rendue sale, il n'est donc pas facile de savoir quand c'était aussi la méthode actuelle. Puisque Linux a également changé le VCS, il est assez difficile de retracer l'historique avant la version 2.6.12. Dans 2.4.20 j'avais, il y avait du code pour le rendre sale lors d'une erreur d'écriture.

Résumé

Ainsi, contrairement à NetBSD, macOS, qui est généralement appelé BSD, est une méthode d'analyse de page physique, et Solaris, qui était autrefois la norme pour divers systèmes d'exploitation Unix, est également une méthode d'analyse de page physique. Historiquement, au moins 4.4BSD ne vide pas automatiquement le cache de page, ce qui est différent entre macOS, qui a 4.3BSD (et les deux FreeBSD) comme ancêtre, et NetBSD, un descendant de 4.4BSD. Mais pas étonnant.

Recommended Posts

Quand le fichier mmap (2) sera-t-il mis à jour? (3)
Quand le fichier mmap (2) sera-t-il mis à jour? (2)
Quand le fichier mmap (2) sera-t-il mis à jour? (1)
Prédire quand l'ISS sera visible
"Solution temporaire" lorsque pip ne peut pas être mis à jour [Python]
Soyez prudent lorsque vous travaillez avec des fichiers texte compressés au format gzip
[Python] Quand les variables sont-elles créées? Quand les instances de classe seront-elles effacées?
Reverse pull Numpy / Pandas (sera mis à jour à tout moment)
Lorsque l'USB n'a pas pu être formaté
Lorsque pydub ne peut pas être installé