Vous mentionnez comment, si le code est spécifique à une CPU, pourquoi doit-il l'être également à un système d'exploitation? C’est en fait une question plus intéressante que beaucoup des réponses proposées ici.
Modèle de sécurité du processeur
Le premier programme exécuté sur la plupart des architectures de CPU s'exécute dans ce qu'on appelle l'anneau interne ou anneau 0 . La manière dont une arche de processeur spécifique implémente des anneaux varie, mais il est évident que presque tous les processeurs modernes ont au moins deux modes de fonctionnement, l'un privilégié, qui exécute un code «bare metal» pouvant effectuer toutes les opérations légales que le processeur peut effectuer et l'autre. non approuvé et exécute un code protégé qui ne peut exécuter qu'un ensemble de capacités sécurisé défini. Certains processeurs ont cependant une granularité beaucoup plus élevée et pour pouvoir utiliser les VM de manière sécurisée, il faut au moins 1 ou 2 sonneries supplémentaires (souvent étiquetées avec des nombres négatifs), mais cela dépasse le cadre de cette réponse.
Où l'OS entre en jeu
Premiers systèmes d'exploitation à tâche unique
Dans les tout premiers systèmes DOS et autres systèmes basés sur des tâches uniques, tout le code était exécuté dans l'anneau interne. Chaque programme que vous exécutiez disposait alors du pouvoir absolu sur tout l'ordinateur et pouvait littéralement faire n'importe quoi s'il se comportait mal, y compris effacer toutes vos données ou même endommager le matériel. dans quelques cas extrêmes tels que la définition de modes d'affichage non valides sur de très vieux écrans, cela pourrait être dû à un code buggy sans aucune malveillance.
Ce code était en fait largement indépendant des systèmes d’exploitation, tant que vous disposiez d’un chargeur capable de charger le programme en mémoire (assez simple pour les premiers formats binaires) et que le code ne reposait sur aucun pilote, implémentant tous les accès matériels auxquels il était destiné. n’importe quel système d’exploitation tant qu’il est exécuté dans l’anneau 0. Remarque: un système d’exploitation très simple comme celui-ci est généralement appelé moniteur s’il est simplement utilisé pour exécuter d’autres programmes sans offrir aucune fonctionnalité supplémentaire.
Systèmes d'exploitation multitâches modernes
Des systèmes d’exploitation plus modernes, notamment UNIX , des versions de Windows commençant par NT et divers autres systèmes d’exploitation devenus obscurs, ont décidé d’améliorer cette situation. Les utilisateurs souhaitaient des fonctionnalités supplémentaires telles que le multitâche afin de pouvoir exécuter plusieurs applications à la fois et une protection, de sorte qu'un bogue ( code malveillant) dans une application ne peut plus causer de dommages illimités à la machine et aux données.
Cela a été fait en utilisant les anneaux mentionnés ci-dessus, le système d'exploitation prendrait la place unique dans l'anneau 0 et les applications s'exécuteraient dans les anneaux externes non fiables, ne pouvant effectuer qu'un ensemble restreint d'opérations autorisées par le système d'exploitation.
Cependant, cette utilité et cette protection accrues avaient un coût, les programmes devaient désormais travailler avec le système d'exploitation pour effectuer des tâches qu'ils n'étaient pas autorisés à effectuer eux-mêmes; ils ne pouvaient par exemple plus prendre le contrôle direct du disque dur en accédant à sa mémoire et en modifiant les paramètres de façon arbitraire. données, au lieu de cela, ils ont dû demander au système d’exécuter ces tâches pour pouvoir vérifier s’ils étaient autorisés à effectuer l’opération, sans modifier les fichiers qui ne leur appartenaient pas, cela vérifierait également la validité de l’opération et ne laisserait pas le matériel dans un état non défini.
Chaque système d’exploitation a choisi une implémentation différente pour ces protections, basée en partie sur l’architecture pour laquelle le système d’exploitation avait été conçue et basée en partie sur la conception et les principes du système d’exploitation en question. les fonctionnalités disponibles pour cela alors que Windows a été conçue pour être plus simple, pour fonctionner sur du matériel plus lent avec un seul utilisateur. La manière dont les programmes de l'espace utilisateur communiquent également avec le système d'exploitation est complètement différente sur X86 comme sur ARM ou MIPS, par exemple, obligeant un système d'exploitation multi-plateforme à prendre des décisions en fonction du besoin de travailler sur le matériel pour lequel il est ciblé.
Ces interactions spécifiques au système d'exploitation sont généralement appelées "appels système" et englobent la manière dont un programme d'espace utilisateur interagit complètement avec le matériel via le système d'exploitation. Elles diffèrent fondamentalement en fonction de la fonction du système d'exploitation. être spécifique à l'OS.
Le chargeur de programme
En plus des appels système, chaque système d' exploitation fournit une méthode différente pour charger un programme à partir du support de stockage secondaire , et dans la mémoire , pour être chargeable par un système d' exploitation spécifique , le programme doit contenir un en- tête spécial décrit à l'OS comment elle peut être chargé et couru.
Cet en-tête était assez simple pour écrire un chargeur pour un format différent était presque trivial. Cependant, avec les formats modernes tels que elf qui supporte des fonctionnalités avancées telles que la liaison dynamique et les déclarations faibles, il est maintenant presque impossible pour un système d'exploitation d'essayer de charger des fichiers binaires ce qui signifie que même s'il n'y avait pas d'incompatibilités entre les appels système, il est extrêmement difficile de placer un programme en mémoire de manière à ce qu'il puisse être exécuté.
Bibliothèques
Les programmes utilisent rarement les appels système directement, cependant, ils obtiennent presque exclusivement leurs fonctionnalités bien que les bibliothèques encapsulent les appels système dans un format légèrement plus convivial pour le langage de programmation, par exemple, C possède la bibliothèque standard C et la glibc sous Linux et les bibliothèques win32 sous Windows NT et supérieur, la plupart des autres langages de programmation ont également des bibliothèques similaires qui encapsulent les fonctionnalités du système de manière appropriée.
Ces bibliothèques peuvent même, dans une certaine mesure, résoudre les problèmes multi-plateformes décrits ci-dessus. Il existe une gamme de bibliothèques conçues pour fournir une plate-forme uniforme aux applications tout en gérant en interne les appels vers une large gamme de systèmes d’exploitation tels que SDL . les programmes ne peuvent pas être compatibles binaires, les programmes qui utilisent ces bibliothèques peuvent avoir une source commune entre les plates-formes, ce qui rend le portage aussi simple que la recompilation.
Exceptions à ce qui précède
Malgré tout ce que j'ai dit ici, il y a eu des tentatives pour surmonter les limitations de l'impossibilité d'exécuter des programmes sur plusieurs systèmes d'exploitation. Parmi les bons exemples, citons le projet Wine, qui a émulé avec succès le chargeur de programme win32, le format binaire et les bibliothèques système permettant aux programmes Windows de s'exécuter sous divers UNIX. Il existe également une couche de compatibilité permettant à plusieurs systèmes d’exploitation BSD UNIX d’exécuter un logiciel Linux et, bien entendu, au propre logiciel d’impression d’Apple permettant d’exécuter un ancien logiciel MacOS sous MacOS X.
Cependant, ces projets nécessitent des efforts de développement manuels considérables. En fonction de la différence entre les deux systèmes d’exploitation, la difficulté varie d’une cale d’impression assez petite à une émulation presque complète de l’autre système d’exploitation, qui est souvent plus complexe que l’écriture de tout un système d’exploitation. C’est donc une exception et non la règle.