Comment exécuter le programme? Où les systèmes d'exploitation entrent en jeu?

StackOverflow https://stackoverflow.com/questions/1599434

  •  22-09-2019
  •  | 
  •  

Question

Un programme est compilé à partir de certaines langues à l'ASM -> Code de machine (directement exécutable). Quand les gens disent que cela dépend la plate-forme, la moyenne que les binaires formés fonctionneront (correctement) que sur les CPU avec la même architecture de jeu d'instructions x86 comme, x86-64. Il peut (à tort) / ne peut pas (du tout) fonctionnent sur d'autres processus en raison de la différence dans ISA. Droit?

Maintenant, le concept de binaires me prêter à confusion. Tout est sur le « Machine Code de langue » et « CPU ». D'où vient le système d'exploitation entrent en jeu? Je veux dire le binaire compilé a des instructions directes pour CPU lorsqu'il est chargé dans la mémoire. Et CPU exécute une instruction à la fois. Je ne pouvais pas voir le rôle du système d'exploitation partout à l'exception de la gestion des processus lien texte . Il doit être en cours d'exécution sur la CPU de même ISA indépendamment du système d'exploitation. droite?

Et pourtant ce ne est pas le cas. Si je construis un code x86 sur la machine windows. Il ne fonctionne pas sur la machine x86 Mac ou machine Linux x86.

Il me manque quelque chose. S'il vous plaît effacer ma confusion.

Était-ce utile?

La solution

Pour commencer, une unité centrale de traitement moderne a (au moins) deux modes, un mode dans lequel il fonctionne le noyau du système d'exploitation lui-même ( « mode noyau ») et un mode dans lequel il est des programmes en cours d'exécution ( « mode utilisateur ») . En mode utilisateur, la CPU ne peut pas faire beaucoup de choses.

Par exemple, un clic de souris est généralement remarqué dans le noyau, pas en mode utilisateur. Cependant, le système d'exploitation envoie l'événement en mode utilisateur et de là, au bon programme. Dans l'autre sens exige également la coopération: un programme ne peut pas tirer à l'écran librement, mais doit passer par le mode OS et noyau pour tirer parti de sa part.

De même, le fait de commencer un programme est généralement une coopération. La partie de la coque du système d'exploitation est un programme en mode utilisateur aussi. Il obtient votre clic de souris, et détermine qu'il est un clic de souris destiné à lancer un processus. La coquille indique alors la partie en mode noyau du système d'exploitation pour démarrer un nouveau processus pour ce programme.

Lorsque le mode noyau doit commencer un nouveau processus, il alloue d'abord la mémoire pour la comptabilité, puis procède à charger le programme. Cela implique la récupération des instructions du binaire, mais également de relier le programme à l'OS. Cela nécessite généralement de trouver le point d'entrée (int main(int argc, char** argv) classique) du binaire, et tous les points où le programme veut appeler le système d'exploitation.

Les différents systèmes d'exploitation utilisent différents moyens pour raccorder des programmes avec le système d'exploitation. En conséquence, le processus de chargement est différent, et les formats de fichiers pour les binaires peuvent différer aussi. Ce n'est pas absolue; le format ELF pour les binaires est utilisé pour un certain nombre de systèmes d'exploitation et Microsoft utilise son format PE sur tous ses systèmes actuels d'exploitation. Dans les deux cas, le format ne décrit le format précis du binaire, de sorte que le système d'exploitation peut décider si le programme peut être raccordé au système d'exploitation. Par exemple, si elle est un binaire Win32, il sera dans le format PE, donc Linux ne se charge pas que, Windows 2000, tout comme de Windows 7-64. Un binaire Win64 d'autre part est au format PE aussi, mais Windows 2000 rejeter.

Autres conseils

Il ne fonctionnera pas sur d'autres processeurs puisque 01010110011 signifie quelque chose sur x86 et quelque chose d'autre sur ARM. x86-64 arrive à être rétrocompatible avec x86 il peut exécuter des programmes x86.

Le binaire est dans un format spécifique que votre système d'exploitation comprend (windows = PE, mac / linux = ELF)

Avec un binaire normale, vos charges OS en mémoire et remplit un certain nombre de champs avec certaines valeurs. Ces « certaines valeurs » sont des adresses à des fonctions de api qui existent dans les bibliothèques partagées (dll, donc), comme kernel32 ou libc. Les adresses API sont nécessaires parce que le binaire lui-même ne sait pas comment accéder à des disques durs, cartes réseau, etc. gamepads Le programme utilise ces adresses pour invoquer certaines fonctions qui existent dans votre système d'exploitation ou dans d'autres bibliothèques.

En substance, le binaire manque quelques éléments essentiels qui doivent être remplies par le système d'exploitation pour faire fonctionner le tout. Si le système d'exploitation remplit les mauvaises pièces, le binaire ne fonctionnera pas car ils ne peuvent pas communiquer entre eux. C'est ce qui se passerait si vous devez remplacer user32.dll avec un autre fichier, ou si vous essayez d'exécuter un fichier exécutable linux sur mac osx.

Alors, comment libc ne sait comment ouvrir un fichier?

libc utilise syscalls, qui est un accès de bas niveau pour les fonctions de base du système d'exploitation. Il est un peu comme un appel de fonction, sauf que vous le faites en remplissant certains registres CPU et le déclenchement d'une interruption (instruction CPU spéciale)

Alors, comment le système d'exploitation puis savoir comment ouvrir les fichiers?

C'est l'une des choses un OS fait. Mais comment savoir comment parler à un disque dur? Je ne sais pas exactement comment ça fonctionne, mais je suppose que le système d'exploitation le fait en écrivant / lecture de certains emplacements de mémoire qui se trouvent être mis en correspondance avec les fonctions du BIOS.

Alors, comment le BIOS doit savoir comment parler à un disque dur?

Je ne sais pas non plus, je ne l'ai jamais fait aucune programmation à ce niveau. Je suppose que le BIOS est cablé aux connecteurs de disque dur et est en mesure d'envoyer la séquence correcte de 1 et de 0 à parler « SATA » avec le disque dur. Il ne peut probablement dire des choses simples comme « lire ce secteur »

Alors, comment le disque dur savent lire un secteur?

Je ne sais vraiment pas du tout, donc je vais laisser un type de matériel continuer.

Deux façons:

D'abord et avant tout la réponse est « appels système ». Chaque fois que vous appelez une fonction qui a besoin de faire des E / S, interagir avec les périphériques, allouer de la mémoire, les processus de fourche, etc., cette fonction doit faire un « appel système ». Alors que l'instruction syscall lui-même fait partie de X86, les appels système disponibles et les paramètres sont spécifiques à OS.

Même si votre programme ne fait aucun appel du système (que je ne suis pas sûr est possible, et ne serait certainement pas très utile) les formats qui enveloppent autour du code de la machine sont différentes pour les différents systèmes d'exploitation. Ainsi, les formats de fichiers de exe (PE) et un exécutable Linux (ELF habituellement) sont différents, ce qui est la raison pour laquelle un fichier exe ne sera pas exécuté sur Linux.

EDIT: ce sont des détails de bas niveau. La réponse de niveau supérieur est de dire que tout ce qui a besoin d'accéder aux fichiers, la console / GUI, allouer de la mémoire, etc. est spécifique à l'OS.

Le système d'exploitation entre en jeu lorsque vous essayez d'accéder à un « service » qu'il fait abstraction pour vous au niveau du matériel, par exemple ouvrir un fichier dans la « base de données » appelé système de fichiers, générer un nombre aléatoire (chaque système d'exploitation moderne dispose de cette fonctionnalité).

Sous GNU / Linux, par exemple, vous devez remplir les registres et appel int 80h pour accéder à un "service" (en fait appelé "syscall").

Votre programme ne fonctionnera pas sur un autre système d'exploitation aussi parce qu'il existe différents formats de fichiers exécutables, par exemple Win a COFF / PE, Linux a le format de fichier ELF (comme tout autre format de fichier, il contient également « méta-données », par exemple le code HTML (ou SGML) format de fichier).

Le système d'exploitation fournit (a) l'environnement que votre code machine fonctionne dans et (b) des services standards. Sans (a), votre code ne sera jamais à exécuter en premier lieu, et sans (b), vous devez mettre en œuvre absolument tout vous et cliquez sur le matériel directement.

Les instructions machine générées par un langage de haut niveau seront appropriés pour les conventions d'appel pour les bibliothèques qui fournissent ces appels que vous faites, y compris les appels système (bien que ceux-ci sont généralement enveloppées dans une bibliothèque de l'espace utilisateur quelque part, donc des détails sur la façon de faire un appel système peut ne pas être nécessaire).

En outre, il sera approprié pour l'architecture de jeu d'instructions ciblé, à quelques exceptions près (il faut prendre soin, par exemple, sur les hypothèses concernant la taille des pointeurs, les types primitifs, mises en page de structure, implémentations de classe en C ++ etc.).

Le format de fichier dictera les crochets nécessaires / fonctions et les données publiquement visibles pour permettre au système d'exploitation pour exécuter votre code en tant que processus, et pour amorcer le processus à l'état requis. Si vous êtes familier avec le développement C / C ++ sous Windows, le concept de sous-système dicte le niveau de bootstrapping, fourni des ressources et la signature de point d'entrée (main(int, char **) normalement sur la plupart des systèmes).

Il y a quelques bons exemples de la façon dont le choix du langage de haut niveau, l'architecture de jeu d'instructions et le format de fichier exécutable peut affecter la capacité d'exécuter un binaire sur un système donné:

langues de l'Assemblée doivent coder pour une ISA spécifique. Ils utilisent des instructions spécifiques à une famille de types de CPU. Ces instructions peuvent travailler sur d'autres familles de processeurs, si les unités centrales prennent en charge le jeu d'instructions donnée. Par exemple le code x86 fonctionnera à un degré, sur un système d'exploitation amd64, et travailler sur une CPU certainement amd64 exécutant un système d'exploitation x86.

C résumés la plupart des détails d'un ISA. A quelques exceptions évidentes comprennent la taille pointeur et boutisme. Diverses interfaces bien connues, seront fournis à un niveau prévu par libc, comme printf, main, fopen, et d'autres. Ceux-ci comprennent les registres prévus et états pile afin de rendre ces appels, ce qui permet le code C pour travailler sur différents systèmes d'exploitation et les architectures sans changement. D'autres interfaces peuvent être fournis, soit directement, soit par enroulement spécifique à la plateforme dans l'interface devrait augmenter la portabilité du code C.

Python et d'autres langages « virtualisés » similaires fonctionnent à un autre niveau d'abstraction, et encore à quelques exceptions près, pour les fonctions d'instance qui n'existent pas sur les plates-formes particulières, ou les différences de codage de caractères, peut fonctionner sans modification sur de nombreux systèmes. Ceci est réalisé en fournissant une interface uniforme pour différentes combinaisons système ISA et d'exploitation, au détriment de la performance et taille de l'exécutable.

Le système d'exploitation fournit les outils et API pour accéder à certaines fonctions et le matériel.

Par exemple, pour créer une fenêtre sur Microsoft Windows, vous avez besoin de DLL du système d'exploitation pour créer la fenêtre.

Sauf si vous voulez écrire l'API vous-même, vous allez utiliser l'API que le système d'exploitation fournit. C'est là le système d'exploitation entrent en jeu.

Aussi je veux Ajouter OS gère le démarrage du programme. Il prépare l'espace de processus et initialisées afin que le programme puisse commencer, charge les instructions du programme et donne le contrôle au programme.

Une analogie:

Dites que vous embauchez un maître d'hôtel d'un autre pays. Il ne comprend pas un mot que vous dites, vous obtenez un dispositif de traducteur comme étoile trek. Maintenant, il peut comprendre votre langage de haut niveau, parce que quand vous parlez, il entend sa propre (plutôt brut) langue.

Supposons maintenant que vous voulez lui de marcher de A à B. Vous ne parleriez pas à ses jambes ou les pieds directement, tu lui demander de son visage! Il est dans le contrôle de son propre corps. Si 1) vous communiquez votre demande correctement et 2) il décide qu'il relève de ses fonctions d'emploi, il se déplace de A à B.

Maintenant, vous obtenez un nouveau serviteur, du même pays que le dernier (parce que vous ne souhaitez pas acheter une nouvelle star-trek-traducteur). Tu veux qu'il marche de A à B aussi. Mais ce serviteur vous oblige à parler plus fort et dire s'il vous plaît en demandant. Vous mettez en place avec cela parce qu'il est plus souple: vous pouvez lui demander d'aller de A à B via C si vous voulez - le maître d'hôtel précédent pourrait le faire, mais traîné ses pieds et se sont plaints.

Une autre coup de chance est que vous pouvez régler vos paramètres de traducteur pour gérer cela, donc, de votre point de vue de la langue, rien ne change. Mais si vous deviez parler à l'ancien maître d'hôtel avec les nouveaux paramètres, il serait confus et ne comprendrait pas même si vous parlez sa langue.

Dans le cas où on ne sait pas, les majordomes sont des ordinateurs avec le même ISA, mais différents systèmes d'exploitation. Le traducteur est votre toolchain compilateur croisé ciblant leur ISA.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top