J'essaie de comprendre pleinement le code de rédaction de processus Pro dans une langue à l'exécution du système d'exploitation. Dans mon cas, la langue serait C et l'OS serait Windows. Jusqu'à présent, j'ai lu beaucoup d'articles différents, mais je ne suis pas sûr, que je comprends bien le processus, et j'aimerais vous demander si vous connaissez de bons articles sur certains sujets que je ne pouvais pas trouver. P>
Alors, qu'est-ce que je pense savoir sur C (et essentiellement d'autres langues): p>
C Compiler lui-même gère uniquement les types de données, les opérations de mathématiques de base, les opérations de pointeurs et le travail avec des fonctions. En travaillant avec des fonctions, je veux dire passer à l'argument et comment obtenir une sortie de fonction. Pendant la compilation, l'appel de la fonction est remplacé par des arguments de passage à la pile et que si la fonction n'est pas en ligne, son appel est remplacé par un symbole pour la liante. Linker que de trouver la définition de la fonction et remplacez le symbole pour passer à une adresse de saut à cette fonction (et bien sûr que de revenir au programme). p>
Si ce qui précède est généralement vrai et que je le comprends, où le dernier fichier .exe en réalité réellement, la liaison enregistre les fonctions? Après la fonction principale ()? Et qu'est-ce qui crée l'en-tête .exe? Compilateur ou lieur? p>
Maintenant, des capacités supplémentaires de C, aujourd'hui connues sous le nom de C Standart Bibliothèque sont définies et les déclarations d'entre eux, que d'autres programmeurs ont écrit pour étendre et simplifier l'utilisation du langage C. Mais ces fonctions telles que Printf () étaient (ou pourraient être?) Écrit dans une langue différente ou une assembleuse. Et il y a ma prochaine question, peut être, par exemple, la fonction Printf () est écrite dans Pure C sans utilisation de l'assembleur? P>
Je sais que c'est une grande question, mais je veux surtout le savoir, le ballon que je suis bien ou non. Et croyez-moi, j'ai lu beaucoup d'articles sur le Web et je ne vous demanderais pas, si je pouvais trouver ces infromations ensemble sur un endroit, dans un article. Je suis inscrit à la pièce par pièce Rassembler des informations, alors je ne suis pas sûr que je suis juste. Merci. P>
3 Réponses :
Je pense que vous êtes exposé à certaines informations moins pertinentes en tant que programmeur C de départ C et que cela pourrait vous déranger - une partie de l'objectif d'utiliser un langage de niveau supérieur comme celui-ci est de ne pas avoir à penser à la manière de penser à la manière d'initialement Ce processus fonctionne. Au fil du temps, cependant, il est important de comprendre le processus. Je pense que vous avez généralement la bonne compréhension de cela. p>
Le compilateur C prend simplement code C et génère des fichiers d'objet contenant la langue de la machine. La majeure partie du fichier d'objet est prise par le contenu des fonctions. Un appel de fonction simple en C, par exemple, serait représenté sous la forme compilée sous forme d'opérateurs de niveau bas pour pousser les éléments dans la pile, modifier le pointeur d'instructions, etc. P>
La bibliothèque C et toute autre bibliothèques que vous utiliseriez sont déjà disponibles dans ce formulaire compilé. P>
La liaison est la chose qui combine tous les fichiers d'objets pertinents, résout toutes les dépendances (par exemple, un fichier d'objet appelant une fonction dans la bibliothèque standard), puis crée l'exécutable. P>
Tant que les bibliothèques de langue sont écrites dans: Pensez à chaque fonction comme une boîte noire. Tant que la boîte noire a une interface standard (la convention d'appel C; c'est-à-dire que cela prend des arguments d'une certaine manière, renvoie des valeurs d'une certaine manière, etc.), comment elle est écrite en interne. Le plus typiquement, les fonctions seraient écrites en C ou directement en montage. Au moment où ils en font un fichier d'objet (ou en tant que bibliothèque compilée), ce n'est pas vraiment important de la création initiale, ce qui compte, c'est qu'ils sont maintenant sous la forme de la machine compilée. P>
Le format d'un exécutable dépend du système d'exploitation, mais une grande partie du corps de l'exécutable dans Windows est très similaire à celle des fichiers d'objet. Imaginez comme si quelqu'un a fusionné ensemble tous les fichiers d'objets, puis a ajouté une colle. La colle charge des trucs liés et invoque ensuite la principale (). Quand j'étais enfant, par exemple, les gens ont eu un coup de pied de "changer la colle" pour ajouter une autre fonction avant la principale () qui afficherait un écran éclaboussable avec son nom. p>
Une chose à noter, cependant, c'est que, quelle que soit la langue que vous utilisez, vous devez éventuellement utiliser les services du système d'exploitation. Par exemple, pour afficher des trucs à l'écran, pour gérer les processus, etc. La plupart des systèmes d'exploitation ont une API qui est également appelable de la même manière, mais son contenu n'est pas inclus dans votre EXE. Par exemple, lorsque vous exécutez votre navigateur, il s'agit d'un exécutable, mais à un moment donné, il y a un appel à l'API Windows pour créer une fenêtre ou charger une police. Si cela faisait partie de votre exe, votre EXE serait énorme. Donc, même dans votre exécutable, il y a des "références manquantes". Habituellement, ceux-ci sont abordés au moment de la charge ou au temps d'exécution, en fonction du système d'exploitation. P>
Merci beaucoup. Donc, juste pour être sûr, lorsque j'ai appelé à fonctionner dans la fonction principale, le lieur ajoutez-vous à cette fonction et appendez cette fonction à la fin du fichier EXE, ou les fonctions situées sur différentes parties du fichier EXE et que le chargeur les connecte réellement ensemble?
Parce que dans l'assembleur 8051, je viens d'ajouter des routines à la fin du programme, et de sauter et de revenir dans les intrognages qui leur sont entrés et sont retournés. Mais pour utiliser le compilateur de saut, devez connaître l'adresse de la première instruction dans la routine. Mais lorsque Windows charge ProGam dans la RAM, le compilateur ne peut pas savoir quelle sera l'adresse de la première instruction de la routine donnée.
Je ne sais pas comment cela fonctionne actuellement dans Windows, mais le chargeur fait généralement beaucoup et peut déplacer des choses. Par exemple, dans les anciens jours de MS DOS, il y avait une limite de la taille des exécutables. Si vous avez eu beaucoup de code supplémentaire, des astuces spéciales étaient nécessaires pour charger et supprimer le code au moment de l'exécution.
Il y a un bon article avancé sur la façon dont la liaison et le chargeur fonctionnent pour Linux: Linuxjournal.com/article/6463 a>. Je pense qu'avec certaines googles, vous pouvez découvrir comment cela fonctionne dans des versions récentes de Windows, mais de manière générale, en tant que programmeur C, vous ne devriez vraiment pas m'inquiéter au-delà de la phase de liaison.
Pour le code 8051, vous exécutez directement sur le processeur. Cela ressemble beaucoup au mode que les noyaux de système d'exploitation fonctionnent sur X86 (et de nombreux autres) processeurs. Votre application s'exécute dans un mode différent permettant au système d'exploitation de remapper la mémoire pour rendre l'application "Pensez" que son code et ses données sont à différents endroits que ce qu'ils sont réellement. Une autre façon de contourner cela est avec le code de la position indépendante. Plutôt que des appels et des sauts aux adresses absolues Les adresses relatives (+ - offset) sont utilisées. Celles-ci, mélangées avec ce qu'est un lieur d'exécution peut faire est de savoir comment cela fonctionne.
Le compilateur est responsable de la traduction de toutes vos fonctions écrites en C en montage, qu'elle enregistre dans le fichier d'objet (DLL ou EXE, par exemple). Donc, si vous écrivez un fichier .C qui a une fonction principale et quelques autres fonctions, le compilateur traduira toutes les personnes en assemblage et les sauvea ensemble dans le fichier EXE. Ensuite, lorsque vous exécutez le fichier, le chargeur (qui fait partie du système d'exploitation) sait commencer à exécuter la fonction principale en premier. Sinon, la fonction principale est comme n'importe quelle autre fonction pour le compilateur. P>
La liaison est responsable de la résolution des références entre les fonctions et les variables dans un fichier d'objet avec les références dans d'autres fichiers. Par exemple, si vous appelez PrintF (), puisque vous ne définissez pas vous-même la fonction printf () vous-même, le linker est responsable de s'assurer que l'appel à imprimerf () va à la bibliothèque système droite où PrintF () est défini. Cela se fait à la compilée. P>
Printf () est en effet écrit dans pure C. Qu'est-ce que cela fait, c'est appeler un appel système dans le système d'exploitation qui sait-il envoyer des caractères à la sortie standard (comme une borne de fenêtre). Lorsque vous appelez Printf () dans votre programme, lors de la compilation, la liaison est responsable de la liaison de votre appel à la fonction PrintF () dans les bibliothèques C Standard C. Lorsque la fonction est transmise au temps d'exécution, PrintF () formate correctement les arguments, puis appelle l'appel du système d'exploitation approprié pour afficher réellement les caractères. p>
Je suis un nouvel utilisateur et ce système ne me permet pas de poster plus d'un lien. Pour contourner cette restriction, j'ai posté une idée de mon blog http://zhinkaas.blogspot.com/2010/04/how-does-c-program-work.html . Il m'a fallu un peu de temps pour obtenir tous les liens, mais en totalité, ceux-ci devraient vous aider à démarrer. P>
Je vous recommanderais d'apprendre à programmer en premier. Tout bon livre de programmation vous indiquera le flux de travail général de la liaison et de la compilation.