Du Rust dans le noyau de Windows

Du Rust dans le noyau de Windows

Du Rust dans le noyau de Windows

David Weston, vice-président de Microsoft et directeur de la sécurité du système d'exploitation Windows, a annoncé l'arrivée de Rust dans le noyau de l'OS à la conférence BlueHat IL 2023 de Tel Aviv, rapporte The Register. Certaines bibliothèques du système d'exploitation sont en cours de réécriture dans le langage de plus en plus adopté dans ce monde industriel pour sa robustesse et sa fiabilité.

« Windows démarrera avec Rust dans son noyau dans les semaines ou les mois à venir, ce qui est vraiment génial » s'est enthousiasmé Weston. Rust permet notamment de sécuriser l'utilisation de la mémoire en s'assurant qu'une référence pointe vers une donnée valide.

Le noyau de Linux, lui, inclut la possibilité de code en Rust depuis la version 6.1 sortie en décembre dernier.

Commentaires (50)


Bonne nouvelle !
Bon il ne faut pas se leurrer non plus, on n’est pas près d’avoir un noyau 100% réécrit en Rust. (je suis persuadé qui doit rester des morceaux de code qui ont 40ans de l’époque de NT3)


J’ai l’impression que l’époque où la volonté de ré-écrire tout le kernel Windows en C♯ est un peu révolu.
“back to the metal”


Je doute fortement qu’il y ait eu une volonté de réécrire le kernel Windows en C#. Les spécificités et les contraintes d’un kernel le rendent peu compatible avec un langage de haut niveau, et incompatible avec un langage à ramasse-miettes.



Sans oublier que le .net nécessite un runtime. Runtime nécessitant un OS pour fonctionner.



Tu confonds peut être avec les API, où Microsoft aimerait plus ou moins abandonner la dépendance forte à Win32 pour son système, pour que cela devienne une brique optionnelle et non plus obligatoire.


Euh … ça urait été complètement “con” de réécrire le kernel en C#, vu que le C# en compilé en bytecode, et pas en code “natif” pour les processeurs …



Edit : grillé à quelques secondes 😅


Bill2

Euh … ça urait été complètement “con” de réécrire le kernel en C#, vu que le C# en compilé en bytecode, et pas en code “natif” pour les processeurs …



Edit : grillé à quelques secondes 😅


CoreRt est capable de faire du natif depuis un moment déjà. Et du bare metal aussi, Pour du c#, pas forcement le full runtime / mais tu a déjà de quoi faire.



Je remet pas en cause l’inutilité de réécrire le noyaux en c# pas contre


Rust commence a faire son chemin dans l’écriture des OS, c’est bien.



On peut seulement regretter qu’il ait fallu attendre 50 ans pour qu’on se dise que le langage C méritait une surcouche syntaxique pour minimiser les erreurs courantes de conception, en particulier les accès aux zones de la mémoire.



Quand on y réfléchit, que de temps perdu en solutions alternatives (parfois hardware !) pour détecter/empêcher les accès invalides à la mémoire et les failles de sécurité qui en découlent.



fdorin a dit:


Je doute fortement qu’il y ait eu une volonté de réécrire le kernel Windows en C#.
Les spécificités et les contraintes d’un kernel le rendent peu compatible avec un langage de haut niveau, et incompatible avec un langage à ramasse-miettes.




Il fait sans doute référence à Singularity où seul le bootstrap et le HAL sont en C/C++. Le kernel est bel et bien en C# (runtime + garbage collector).


Je l’avais oublié ce projet ^^.



Singularity est un microkernel, pas un kernel, et les opérations de bas niveau sont bien en assembleur/C/C++.



Ce projet n’a jamais eu pour vocation de remplacer le noyau de Windows. C’était seulement un projet de recherche.




Le kernel est bel et bien en C# (runtime + garbage collector).




Pour chipoter : non. C’est en Sing# (qui est une extension d’une extension de C#). :cap:


Avec quel compilateur Microsoft va-t-il pouvoir compiler Rust ? Je doute qu’ils utilisent Rust LLVM.



Si je ne dis pas de bêtise : le projet analogue pour le noyau Linux ne fonctionne que lorsque celui-ci est compilé avec Clang/LLVM et non GCC.



(quote:2131362:127.0.0.1)
On peut seulement regretter qu’il ait fallu attendre 50 ans pour qu’on se dise que le langage C méritait une surcouche




Moi ce qui me fascine c’est la vitesse à laquelle le C (et surtout le C++ qui etait uniquement mal vu des guru) ont baissé dans l’opinion des dev-influenceur-twitch-o-twitter en l’espace de 2ans simplement à cause du gain de popularité de Rust.



C’était considéré comme le(s) langage(s) indétrônable pour faire du code performant et maintenant on voit de + en + de troll à leur encontre et d’alternatives qui pop comme des champignons (carbon, zig, odin…)



vloz a dit:


Moi ce qui me fascine c’est la vitesse à laquelle le C (et surtout le C++ qui etait uniquement mal vu des guru) ont baissé dans l’opinion des dev-influenceur-twitch-o-twitter en l’espace de 2ans simplement à cause du gain de popularité de Rust.




On ne vit pas dans le même monde, visiblement.
https://www.lemondeinformatique.fr/actualites/lire-la-popularite-du-langage-c-en-constante-progression-89464.html


“ont baissé dans l’opinion des dev-influenceur-twitch-o-twitter ”
=> me sort l’index tiobe.


vloz

“ont baissé dans l’opinion des dev-influenceur-twitch-o-twitter ”
=> me sort l’index tiobe.


Désolé, je m’étais arrêté à “dev”. Je ne savais même pas qu’il y avait des influenceurs sur Twitch pour du développement (oui, je suis old school).



fdorin a dit:


Singularity est un microkernel, pas un kernel, et les opérations de bas niveau sont bien en assembleur/C/C++.




Hmm… non, pas vraiment.




  • Les opérations de bas niveau du kernel sont en langage machine (obviously) et ce langage machine vient de code C#/Sing# (compilé au runtime par bartok).

  • Les opérations de bas niveau du HAL sont en langage machine (obviously again) et ce langage machine vient de code C++ (pré-compilé).




vloz a dit:


Moi ce qui me fascine c’est la vitesse à laquelle le C (et surtout le C++ qui etait uniquement mal vu des guru) ont baissé dans l’opinion des dev-influenceur-twitch-o-twitter en l’espace de 2ans simplement à cause du gain de popularité de Rust.




Les dev-influenceurs ne sont pas représentatifs des usages, comme le disent les commentaires ci-dessus. Ces influenceurs cherchent a promouvoir leur nouveau langage de prédilection, mais c’est souvent des langages de niche ou des trucs sémantiquement équivalent à des trucs qui existent déjà…



(quote:2131362:127.0.0.1)
Quand on y réfléchit, que de temps perdu en solutions alternatives (parfois hardware !) pour détecter/empêcher les accès invalides à la mémoire et les failles de sécurité qui en découlent.




Tu peux préciser ? Je me souviens que l’implémentation de la gestion mémoire par le CPU (la fameuse MMU de son premier petit nom) n’est pas apparue sans un besoin à la base. Un vrai besoin s’entend.




(quote:2131406:127.0.0.1)
Les dev-influenceurs ne sont pas représentatifs des usages, comme le disent les commentaires ci-dessus. Ces influenceurs cherchent a promouvoir leur nouveau langage de prédilection, mais c’est souvent des langages de niche ou des trucs sémantiquement équivalent à des trucs qui existent déjà…




Le problème c’est qu’il font le buzz et sont plus visibles que le bon sens. Une fois que c’est réécris il se passe quoi ? Bin juste la maintenance. Prenons pour exemple le kernel de Windows justement… qui date un peu.



Le problème c’est que ces influenceurs plus ou moins en mode opération de com vont susciter des vocations pour Rust et pour un chantier ponctuel. Parce que bon, quand on dit Rust on entend Microsoft en bruit de fond.



Et cela arrangera bien les demandeurs qui vont pouvoir faire pression sur les salaires. En image. Tu mets le coder sur le bord de la route et il a un écriteau : “Will code Rust for food”…



Donc ça arrange qui ?



TexMex a dit:


Tu peux préciser ? Je me souviens que l’implémentation de la gestion mémoire par le CPU (la fameuse MMU de son premier petit nom) n’est pas apparue sans un besoin à la base. Un vrai besoin s’entend.




Bah tous les trucs qui empêchent les accès non-autorisés à la mémoire: du DEP au MPU, en passant par les techniques d’isolation (MPX…)



(quote:2131406:127.0.0.1)
Hmm… non, pas vraiment.




  • Les opérations de bas niveau du kernel sont en langage machine (obviously) et ce langage machine vient de code C#/Sing# (compilé au runtime par bartok).

  • Les opérations de bas niveau du HAL sont en langage machine (obviously again) et ce langage machine vient de code C++ (pré-compilé).




Il faut s’entendre sur ce que sont les opérations bas niveau. Je ne parle pas des drivers. Je parle de tout le nécessaire obligatoire pour faire un kernel aujourd’hui :




  • gestion de la mémoire

  • gestion des threads (création, ordonnancement, etc.)

  • la couche HAL



Et ça, c’est forcément dans un langage très bas niveau, comme l’assembleur ou le C (même le C++ c’est compliqué, sauf à retirer certaines fonctionnalités comme les exceptions).



Que le kernel propose ensuite des services plus évolués (gestion des processus, système de fichiers, etc.) ou des drivers, oui, ça ça peut être écrit dans des langages plus “haut niveau”.



Mais sur un microkernel, toutes les opérations bas niveau sont dans le kernel à proprement parler. Le reste se trouve dans des “services”.


Pour la gestion de la mémoire, pas besoin d’un langage de très bas niveau. Il faut juste des pointeurs, ce que C# propose. Pour la couche HAL et la gestion des threads, il faut un accès direct aux registres, et là effectivement ce n’est pas proposé de base par C#, mais on peut imaginer des fonctions spéciales qui sont remplacées à la compilation pour donner l’accès aux registres (c’est déjà le cas pour les registres SSE, AVX, et consors: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.x86.sse?view=net-8.0).



Mais bon, comme ça a été dit à plusieurs reprises déjà, en pratique ça n’a strictement aucun intérêt.



Le noyau de Linux




:cap:



fdorin a dit:


Il faut s’entendre sur ce que sont les opérations bas niveau. Je ne parle pas des drivers. Je parle de tout le nécessaire obligatoire pour faire un kernel aujourd’hui :




  • gestion de la mémoire

  • gestion des threads (création, ordonnancement, etc.)

  • la couche HAL



Et ça, c’est forcément dans un langage très bas niveau, comme l’assembleur ou le C (même le C++ c’est compliqué, sauf à retirer certaines fonctionnalités comme les exceptions).




je pense que tu amalgame C# (le langage) et C#/MSIL/.net (un programme C# compilé en MSIL qui s’exécute sur le runtime).



Singularity est codé en C# (le langage), mais bien évidemment le “binaire” résultant n’est pa du MSIL qui s’exécute pas sur le runtine .Net. Le binaire résultant c’est du bon vieux langage machine qui s’exécute directement sur le CPU.



imagine cela comme un compilateur “C# –> C/C++ –> x86”.



An Overview of the Singularity Project




The Singularity kernel is a privileged system component that controls access to hardware
resources, allocates and reclaims memory, creates and schedules threads, provides intraprocess thread synchronization, and manages I/O. It is written in a mixture of safe and unsafe C# code and runs in its own garbage collected object space.




https://www.researchgate.net/publication/236160050_An_Overview_of_the_Singularity_Project



(quote:2131429:127.0.0.1)
je pense que tu amalgame C# (le langage) et C#/MSIL/.net (un programme C# compilé en MSIL qui s’exécute sur le runtime).




Pas du tout, je connais très bien toutes ces notions et les nuances. Mais je sais aussi que le langage a besoin d’un runtime pour fonctionner (c’est intrinsèque au langage) de par l’absence de gestion de la mémoire (ramasse miettes), de la gestion des exceptions et de la réflexivité (pour ne citer que les aspects principaux).




Singularity est codé en C#




Non. Il est codé en Sing#. Qui est une extension de Spec#, qui est une extension de C#.



Du coup, une extension d’une extension d’un langage, ce n’est plus le même langage. Sinon, on peut dire C++ c’est une extension de C.



Après une lecture rapide de l’article, on se rend compte qu’il y a un abandon/limitation de nombreuses fonctionnalités (la réflexivité existe dans une forme réduite, les données par référence sont absentes de l’ABI, etc.).



Maintenant, en lisant ce passage :




Code in Singularity is either verified or trusted. Verified code’s type and memory safety is
checked by a compiler. Unverifiable code must be trusted by the system and is limited to the
hardware abstraction layer (HAL), kernel, and parts of the run-time system. Most of the kernel is
verifiably safe, but portions are written in assembler, C++, and unsafe C#




On se rend compte aussi d’une chose, c’est de l’ambiguïté quant à l’usage du terme “kernel”, où un coup cela désigne uniquement le microkernel, et à d’autre moment, le noyau dans son intégralité (microkernel + ses composants).



Mon propos, depuis le début, ne concerne que le microkernel. L’article précise que le code non vérifiable est justement dans la HAL, le kernel (qui devrait plutôt être microkernel, mais passons) et certaines parties du runtime. Soit… exactement la position que je défends depuis le début.


Perso, je trouve la nouvelle concernant Rust dans le noyau Windows moins fracassante que celle concernant le remplacement de NTFS par ReFS. Une page se tourne…


Ah bon? Je l’avais loupé le remplacement NTFS par REFS. Je me demande pourquoi leur choix s’est porté sur REFS et pas ZFS.



KooKiz a dit:


Pour la gestion de la mémoire, pas besoin d’un langage de très bas niveau. Il faut juste des pointeurs, ce que C# propose.




Non. Même si on limite les désallocations de mémoire au sein d’un noyau, il est nécessaire de pouvoir désallouer de la mémoire. Ce que ne permet pas de faire le C#.



De plus, le ramasse-miette génère un problème d’indéterminisme, qui peut être très problématique dans le cadre d’opération de bas niveau / manipulation des registres, etc…



fdorin a dit:


Non. Même si on limite les désallocations de mémoire au sein d’un noyau, il est nécessaire de pouvoir désallouer de la mémoire. Ce que ne permet pas de faire le C#.



De plus, le ramasse-miette génère un problème d’indéterminisme, qui peut être très problématique dans le cadre d’opération de bas niveau / manipulation des registres, etc…




Peut être qu’il me manque un concept, ou que ma compréhension est erronée. Au niveau du noyau, je ne pense pas qu’il y ait la notion d’allocation/désallocations ? Le code s’exécutant a accès à l’intégralité de la mémoire physique et l’utilise comme bon lui semble. La notion d’allocation/désallocation est un concept apporté par le langage, et malloc/new vont juste permettre d’éviter de s’emmeler. En pratique, je ne vois pas pourquoi malloc/new ne pourraient pas être réimplémentés en C#.



Pareil pour le garbage collector, il “suffit” de ne pas s’en servir. La manière dont je vois les choses, c’est implémenter un malloc qui retourne des ref struct créés à partir d’adresses mémoires arbitraires. Le garbage collector n’y touchera pas.


Par contre oui, comme je le mentionnais pour la gestion de registre c’est la merde :transpi: Notamment pour implémenter un handler d’interruption, là ça me parait compliqué.



fdorin a dit:


Pas du tout, je connais très bien toutes ces notions et les nuances. Mais je sais aussi que le langage a besoin d’un runtime pour fonctionner (c’est intrinsèque au langage) de par l’absence de gestion de la mémoire (ramasse miettes), de la gestion des exceptions et de la réflexivité (pour ne citer que les aspects principaux).




Le C aussi a besoin d’un runtime pour fonctionner. le C++ aussi. Et pratiquement tous les langages. Dans le cas du C, le runtime est inséré dans le binaire par le compilateur donc on a tendance à oublier qu’il est là.



google “crt0” pour en savoir plus.



D’ailleurs on peut faire la même chose avec C# avec NativeAOT




Mon propos, depuis le début, ne concerne que le microkernel. L’article précise que le code non vérifiable est justement dans la HAL, le kernel (qui devrait plutôt être microkernel, mais passons) et certaines parties du runtime. Soit… exactement la position que je défends depuis le début.




Deux messages plus haut tu défendais que la “gestion de la mémoire” et la “gestion des threads (création, ordonnancement, etc.)” était “forcément dans un langage très bas niveau, comme l’assembleur ou le C”. Or dans Singularity c’est écrit en Sing#.



(quote:2131447:127.0.0.1)
Le C aussi a besoin d’un runtime pour fonctionner. le C++ aussi. Et pratiquement tous les langages. Dans le cas du C, le runtime est inséré dans le binaire par le compilateur donc on a tendance à oublier qu’il est là.



google “crt0” pour en savoir plus.




Aie aie aie, tu confonds tout. Là, on parle d’un noyau, pas d’un programme. crt0, c’est le code pour démarrer un programme. crt0 n’est pas utilisé dans le cas d’une bibliothèque par exemple.



crt0, c’est lui qui s’assure que la méthode main est appelée, et que les paramètres argc et argv sont correctement initialisés.




Deux messages plus haut tu défendais que la “gestion de la mémoire” et la “gestion des threads (création, ordonnancement, etc.)” était “forcément dans un langage très bas niveau, comme l’assembleur ou le C”. Or dans Singularity c’est écrit en Sing#.




Je persiste pour une raison fort simple : cela nécessite d’accéder à des fonctionnalités propre au CPU, abstraction que ne fourni pas le CIL. Tu ne peux pas faire de context switching sans accès au CPU. Tu ne peux pas gérer la pagination, sans avoir accès à certains registres, gérer les interruptions logicielles & matérielles, etc…



Maintenant, si tu enlèves des fonctionnalités au langage pour n’en garder qu’un sous-ensemble (exit la gestion des exceptions, les créations d’objet, le ramasse-miettes, la réflexivité, etc.) alors oui, là tu peux faire des choses. Tu peux écrire des fonctions et les compiler. Mais c’est un peu fort de café que de dire que c’est du C# (ou du Sing#) vu les limitations imposées. Sinon, il est tout aussi juste de dire que le noyau linux est écrit en grande partie en C++.



KooKiz a dit:


Peut être qu’il me manque un concept, ou que ma compréhension est erronée. Au niveau du noyau, je ne pense pas qu’il y ait la notion d’allocation/désallocations ? Le code s’exécutant a accès à l’intégralité de la mémoire physique et l’utilise comme bon lui semble.




En fait, l’espace physique est mappé sur un espace logique. C’est pour ça que tu peux n’avoir que 4Go de RAM, mais avoir des programmes, librairies, driver, etc… chargé à des emplacement mémoire bien au delà des 0x0004000000000000 comme 0x8000000000000000.
C’est parce que tu peux mapper de la mémoire physique sur des plages “virtuelles”.



D’ailleurs, lorsque ce n’est pas le cas, et que tu tentes d’accéder à une zone de la mémoire non mappée, tu as des interruptions comme des PAGE_FAULT




La notion d’allocation/désallocation est un concept apporté par le langage, et malloc/new vont juste permettre d’éviter de s’emmeler. En pratique, je ne vois pas pourquoi malloc/new ne pourraient pas être réimplémentés en C#.




Non. La notion d’allocation/désallocation n’est pas qu’un concept apporté par le langage. Et il y en a bien besoin au niveau noyau. Sinon, linux n’aura absolument pas besoin d’API comme kalloc pour être utilisée au sein même du noyau.




Pareil pour le garbage collector, il “suffit” de ne pas s’en servir. La manière dont je vois les choses, c’est implémenter un malloc qui retourne des ref struct créés à partir d’adresses mémoires arbitraires. Le garbage collector n’y touchera pas.




Dans ce cas, désactivons le ramasse-miettes. Mais alors, ce n’est plus du C# ! Le ramasse-miettes fait partie du langage, et il n’y a pas moyen aujourd’hui de le désactiver.



S’amuser à gérer manuellement la mémoire en prenant des adresses arbitraires (aie !!), c’est prendre le risque d’un système instable, car le ramasse-miettes ne saura pas si telle ou telle portion est utilisée ou non. Et s’il a besoin de mémoire (par exemple, pour son fonctionnement interne) ou lors d’une instanciation classique ou à cause d’un boxing, cela risque fortement de créer des conflits.



KooKiz a dit:


Pour la gestion de la mémoire, pas besoin d’un langage de très bas niveau. Il faut juste des pointeurs, ce que C# propose.




Euh, non. MMU, table des pages, TLB, ça te dit quelque chose ?




Pour la couche HAL et la gestion des threads, il faut un accès direct aux registres, et là effectivement ce n’est pas proposé de base par C#, mais on peut imaginer des fonctions spéciales qui sont remplacées à la compilation pour donner l’accès aux registres (c’est déjà le cas pour les registres SSE, AVX, et consors: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.x86.sse?view=net-8.0).




Je voudrais bien voir un changement de contexte ou un handler d’IRQ en C#… C’est un peu plus qu’un simple accès aux registres. Il faut maîtriser la convention d’appel, la gestion de la pile, etc.



Euh, non. MMU, table des pages, TLB, ça te dit quelque chose ?




Oui, mais je pensais que ce n’était des concepts utilisés qu’en user space pour partitionner la mémoire des processus ? C’est peut être là que je me trompe.




Non. La notion d’allocation/désallocation n’est pas qu’un concept apporté par le langage. Et il y en a bien besoin au niveau noyau. Sinon, linux n’aura absolument pas besoin d’API comme kalloc pour être utilisée au sein même du noyau.




Comment est implémenté kalloc? Est-ce qu’il dialogue avec le CPU pour changer l’état des pages d’une manière ou d’une autre, ou est-ce qu’il s’occupe juste d’assigner arbitrairement les plages mémoires pour que les drivers ne s’écrasent pas les uns les autres ? Dans mon raisonnement je pars du principe que c’est la seconde hypothèse.
En d’autres termes, si j’écris un driver s’exécutant en mode kernel et que j’accède à une adresse physique arbitraire, est-ce que ça génère une faute ? Je pensais que non, et c’est peut-être mon erreur.




S’amuser à gérer manuellement la mémoire en prenant des adresses arbitraires (aie !!), c’est prendre le risque d’un système instable, car le ramasse-miettes ne saura pas si telle ou telle portion est utilisée ou non. Et s’il a besoin de mémoire (par exemple, pour son fonctionnement interne) ou lors d’une instanciation classique ou à cause d’un boxing, cela risque fortement de créer des conflits.




Dans le pire des cas, il suffit d’allouer un byte array suffisamment large et de l’épingler, et on a ainsi la garantie que la CLR ne va pas utiliser cet espace mémoire par erreur.



Après, encore une fois, je suis le premier à dire que c’est totalement inutile. Je geek juste un peu sur la possibilité technique.



KooKiz a dit:


Oui, mais je pensais que ce n’était des concepts utilisés qu’en user space pour partitionner la mémoire des processus ? C’est peut être là que je me trompe.




Oui, tu te trompes. Tu faisais la sieste pendant les cours de système ?
La virtualisation de la mémoire est entièrement pilotée par le noyau, et justement l’espace utilisateur n’a pas le contrôle dessus.



(quote:2131464:alex.d.)
Oui, tu te trompes. Tu faisais la sieste pendant les cours de système ? La virtualisation de la mémoire est entièrement pilotée par le noyau, et justement l’espace utilisateur n’a pas le contrôle dessus.




Bah oui, mais on parle d’écrire un noyau, donc justement la partie qui pilote cette gestion.



KooKiz a dit:


Bah oui, mais on parle d’écrire un noyau, donc justement la partie qui pilote cette gestion.




En effet. Et écrire une gestion de la table des pages en C#, ça me fait frisonner rien que d’y penser.



KooKiz a dit:



Comment est implémenté kalloc? Est-ce qu’il dialogue avec le CPU pour changer l’état des pages d’une manière ou d’une autre, ou est-ce qu’il s’occupe juste d’assigner arbitrairement les plages mémoires pour que les drivers ne s’écrasent pas les uns les autres ? Dans mon raisonnement je pars du principe que c’est la seconde hypothèse.




Raté, c’est la première ;)




En d’autres termes, si j’écris un driver s’exécutant en mode kernel et que j’accède à une adresse physique arbitraire, est-ce que ça génère une faute ? Je pensais que non, et c’est peut-être mon erreur.




Raté encore, ça génère bien une erreur (histoire d’être précis jusqu’au bout, parce qu’un noyau linux peut être utilisé sur tellement d’architecture différente, c’est le cas pour les architectures x86, x86-64, et beaucoup d’ARM. Bref, tout ce qui peut faire tourner un OS bureau ou serveur)




Dans le pire des cas, il suffit d’allouer un byte array suffisamment large et de l’épingler, et on a ainsi la garantie que la CLR ne va pas utiliser cet espace mémoire par erreur.




Et cet espace, comment est-il alloué par le CLR ? :D



fdorin a dit:




KooKiz a écrit:
Comment est implémenté kalloc? Est-ce qu’il dialogue avec le CPU pour changer l’état des pages d’une manière ou d’une autre, ou est-ce qu’il s’occupe juste d’assigner arbitrairement les plages mémoires pour que les drivers ne s’écrasent pas les uns les autres ? Dans mon raisonnement je pars du principe que c’est la seconde hypothèse.




Raté, c’est la première ;)




Dire que des mecs ont pondu 4000 lignes de code C dans vmalloc.c pour gérer les pages mémoire, alors que @fdorin fait ca simplement en appelant les fonctions du CPU.



Raté encore, ça génère bien une erreur (histoire d’être précis jusqu’au bout, parce qu’un noyau linux peut être utilisé sur tellement d’architecture différente, c’est le cas pour les architectures x86, x86-64, et beaucoup d’ARM. Bref, tout ce qui peut faire tourner un OS bureau ou serveur)




Mon postulat de base était donc erroné, merci pour la clarification. J’irai me documenter un peu sur le sujet quand j’aurai le temps :yes:




Et cet espace, comment est-il alloué par le CLR ? :D




Bon point. Sur les projets comme https://codevision.medium.com/running-c-snake-inside-uefi-df193b6213e2 je partais du principe que l’auteur s’abstenait juste d’allouer sur la heap, mais vu que le GC va aussi allouer ses segments initiaux je réalise que le flag true doit entièrement virer le GC.



(quote:2131484:127.0.0.1)
Dire que des mecs ont pondu 4000 lignes de code C dans vmalloc.c pour gérer les pages mémoire, alors que @fdorin fait ca simplement en appelant les fonctions du CPU.




Reprend ce que dis KooKiz avant de te montrer condescendant.




Comment est implémenté kalloc? Est-ce qu’il dialogue avec le CPU pour changer l’état des pages d’une manière ou d’une autre, ou est-ce qu’il s’occupe juste d’assigner arbitrairement les plages mémoires pour que les drivers ne s’écrasent pas les uns les autres ? Dans mon raisonnement je pars du principe que c’est la seconde hypothèse.




C’est d’une manière ou d’une autre. Et non sa seconde hypothèse. Maintenant, je n’ai jamais dis que c’était simple et qu’il suffisait de changer un flag au CPU.



Bonne soirée à toi.



Bill2 a dit:


Euh … ça urait été complètement “con” de réécrire le kernel en C#, vu que le C# en compilé en bytecode, et pas en code “natif” pour les processeurs …




NGEN.exe est fournit avec C# au moins depuis le 2.0 et permet de compiler en natif. Rien n’empêche d’avoir un bytecode et de le compiler en natif localement un fois à l’install.




(quote:2131362:127.0.0.1)
Rust commence a faire son chemin dans l’écriture des OS, c’est bien.



On peut seulement regretter qu’il ait fallu attendre 50 ans pour qu’on se dise que le langage C méritait une surcouche syntaxique pour minimiser les erreurs courantes de conception, en particulier les accès aux zones de la mémoire.




Je crois que les surcouches syntaxiques on les a eu (plus dans C++ que C, mais elles sont là).
On au aussi eu d’autres langages, mais aucun n’a percé (trop boîte noire j’imagine, le C étant proche de l’assembleur dans les possibilités offertes)



fdorin a dit:


Non. Même si on limite les désallocations de mémoire au sein d’un noyau, il est nécessaire de pouvoir désallouer de la mémoire. Ce que ne permet pas de faire le C#.
De plus, le ramasse-miette génère un problème d’indéterminisme, qui peut être très problématique dans le cadre d’opération de bas niveau / manipulation des registres, etc…




En fait, C# permet depuis le début de gérer la mémoire unsafe et de forcer la désallocation (de différentes manières: soit tu joues avec l’API d’allocation mémoire - ou les APIs, soit tu gères précisément via Dispose()), pas besoin d’attendre le ramasse-miette forcément pour libérer des ressources systèmes.



Pour les opérations bas niveau/manipulation des registres: on peut faire un micro kernel avec un HAL - mine de rien c’est un peu ce qu’on fait avec l’IA: on charge des modèles dans des KPU/NPU, mais le code machine du NPU/KPU on ne le connaît pas. Un peu comme si on cpiliait un firmware en le chargeant.




KooKiz a dit:


Par contre oui, comme je le mentionnais pour la gestion de registre c’est la merde :transpi: Notamment pour implémenter un handler d’interruption, là ça me parait compliqué.




Et pourtant… Sous des systèmes comme OpenVMS, tu peux même lancer une appli lorsqu’un interruption survient (certainement un héritage du PDP11…pour optimiser on peut précharger l’image en RAM avant que l’interruption ne survienne). Ca se configure en script. Donc ça peut exister




TexMex a dit:


Tu peux préciser ? Je me souviens que l’implémentation de la gestion mémoire par le CPU (la fameuse MMU de son premier petit nom) n’est pas apparue sans un besoin à la base. Un vrai besoin s’entend.




En plus des instructions pour RETPOTLINE (support semi-matériel pour SPECTRE), tu as par exemple:




  • L’allocation de mémoire aléatoire

  • Les adresses aléatoires des routines

  • L’execution bit

  • Sur mon PC AMD: chiffrement de la RAM (visiblement liée au processus)

  • Différentes techniques pour grouper les processus “vérifiés” sur certains noyaux pour ne plus partager le cache (là je ne sais pas s’il y a une part de matériel)



Plusieurs de ces solutions ont un impact plus ou moins visible sur les perfs…



Wosgien a dit:


En fait, C# permet depuis le début de gérer la mémoire unsafe et de forcer la désallocation (de différentes manières: soit tu joues avec l’API d’allocation mémoire - ou les APIs, soit tu gères précisément via Dispose()), pas besoin d’attendre le ramasse-miette forcément pour libérer des ressources systèmes.




C’est une erreur de croire ça. La mémoire est gérée et le développeur n’a pas la main dessus. Dispose, les “destructeurs”, etc… c’est bon pour libérer les ressources autre que la mémoire, mais la mémoire, tu n’as pas la main dessus. Jamais.



J’avais écrit il y a quelques années des articles au sujet du ramasse-miettes .Net sur developpez.com (partie 1, partie 2) si tu souhaites approfondir ;)



Quant à la gestion de la mémoire unsafe, il s’agit :




  • soit pour des raisons d’optimisation, d’utiliser des pointeurs sur des structures managées ;

  • soit pour des raisons d’appels de code natif, d’utiliser des structures de données allouées en dehors de la plateforme.



Mais tu ne peux pas lui dire : alloues moi 18 octets, je fais ma tambouille, puis libère ces 18 octets. C’est impossible.


Et merci pour les articles, je les ai montrés à des collègues à leur sortie!!



fdorin a dit:


Reprend ce que dis KooKiz avant de te montrer condescendant.
C’est d’une manière ou d’une autre. Et non sa seconde hypothèse. Maintenant, je n’ai jamais dis que c’était simple et qu’il suffisait de changer un flag au CPU.




Toujours pas.



Tu trouveras sur wikipedia un joli schéma explicatif des couches du noyau linux:





La gestion mémoire c’est la colonne verte.
Dans cette colonne, la seule couche en lien avec le MMU hardware c’est le bloc “physical memory operations” (en bas du schéma).



Le code qui correspond à ce bloc pour le x64 c’est:





Et dans ce code, nul appel mystérieux pour changer l’état des pages.
Pour la bonne raison que c’est fait par le code C dans les fichiers:






Bonne soirée à toi.




Bonne soirée également. :smack:



fdorin a dit:


C’est une erreur de croire ça. La mémoire est gérée et le développeur n’a pas la main dessus. Dispose, les “destructeurs”, etc… c’est bon pour libérer les ressources autre que la mémoire, mais la mémoire, tu n’as pas la main dessus. Jamais.




Sauf à jouer avec VirtualAlloc, VirtualFree et autres appels “à la main”.



(quote:2131517:127.0.0.1)
Toujours pas.




Mais tu cherches à démontrer quoi exactement ? Tu donnes une collection de liens, mais dans quel but ?



La gestion de l’allocation de la mémoire, c’est un truc complexe qui mélange pas mal d’algorithmie (gestion des pages, mapping, etc.) et de la configuration du MMU.



La question de KooKiz à laquelle je répond est la suivante :




  • est-ce qu’il s’occupe juste d’assigner arbitrairement les plages mémoires ? Non

  • est-ce qu’il dialogue avec le CPU pour changer l’état des pages d’une manière ou d’une autre ? Oui.



Sachant que sur les architectures “classiques”, le MMU est intégré au CPU. Donc ok, c’est un léger abus de langage de dire que l’on dialogue avec CPU au lieu de dire MMU, mais ça ne change rien à la réponse que j’ai faite.



On peut même aller plus loin en disant qu’une partie du dialogue est faite directement à partir de la RAM. Mais il faut configurer des registres (le CR3 de mémoire) ainsi que des TSS.



Wosgien a dit:


Sauf à jouer avec VirtualAlloc, VirtualFree et autres appels “à la main”.




Ah mais dans ce cas, c’est de la mémoire non managée, c’est totalement différent ;)




Et merci pour les articles, je les ai montrés à des collègues à leur sortie!!




:iloveyou: :smack:



(quote:2131421:127.0.0.1)
Bah tous les trucs qui empêchent les accès non-autorisés à la mémoire: du DEP au MPU, en passant par les techniques d’isolation (MPX…)




Bah ce n’est pas du temps perdu si cela répond à un besoin.



fdorin a dit:


Mais tu cherches à démontrer quoi exactement ? Tu donnes une collection de liens, mais dans quel but ?




Répondre correctement à la question posée par KooKiz, en donnant des liens qui lui permettent de corroborer (ou pas) mon assertion.



Bref, le principe d’une démarche scientifique.
Et pas pas un simple argument d’autorité de quelqu’un qui répondrait juste “oui” ou “non” :D



(quote:2131596:127.0.0.1)
Répondre correctement à la question posée par KooKiz, en donnant des liens qui lui permettent de corroborer (ou pas) mon assertion.




D’accord. Là où j’ai choisi la pédagogie, tu as choisi de noyer la personne sous les détails techniques qui nécessitent des heures de lecture pour un dev averti. Chacun son choix :D



Sinon, tu peux donner aussi la doc d’intel (https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html) bien touffue et sacrément indigeste (pour l’avoir lu il y a de nombreuses années).




Bref, le principe d’une démarche scientifique. Et pas pas un simple argument d’autorité de quelqu’un qui répondrait juste “oui” ou “non” :D




Ah non, c’est pas ça un argument d’autorité. Va falloir revoir la définition ;) J’aurais été Linus Torvalds, je dis pas, mais c’est pas le cas :mdr:



J’ai répondu sans vraiment étayer (pour privilégier la pédagogie), mais je n’ai pas usé de l’argument d’autorité ;)


Pendant ce temps, à Vera Cruz … je compile / installe GCC 13.1 :)


Fermer