Comment un programme C commence-t-il?
Réponses
Trop de publicités?Le système d'exploitation appelle l' main()
fonction. En fait, il appelle généralement quelque chose d'autre nommé une chose étrange comme _init
. Le compilateur C, des liens, une bibliothèque standard de chaque application qui fournit ce système d'exploitation défini de point d'entrée, puis appelle main()
.
Edit: Évidemment, cela n'a pas été détaillée et correcte suffisant pour certaines personnes.
L' Exécutable et Linkable Format (ELF) laquelle de nombreux systèmes d'exploitation Unix utilisation définit un point d'entrée de l'adresse. C'est là que le programme commence à courir après les OS termine exec()
appel. Sur un système Linux, c'est _init.
De objdump -d:
Disassembly of section .init:
08049f08 <_init>:
8049f08: 55 push %ebp
8049f09: 89 e5 mov %esp,%ebp
8049f0b: 83 ec 08 sub $0x8,%esp
8049f0e: e8 a1 05 00 00 call 804a4b4 <call_gmon_start>
8049f13: e8 f8 05 00 00 call 804a510 <frame_dummy>
8049f18: e8 d3 50 00 00 call 804eff0 <__do_global_ctors_aux>
8049f1d: c9 leave
8049f1e: c3 ret
De readelf -d:
0x00000001 (NEEDED) Shared library: [libstdc++.so.6]
0x00000001 (NEEDED) Shared library: [libm.so.6]
0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x00000001 (NEEDED) Shared library: [libpthread.so.0]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000c (INIT) 0x8049f08
0x0000000d (FINI) 0x804f018
0x00000004 (HASH) 0x8048168
0x00000005 (STRTAB) 0x8048d8c
0x00000006 (SYMTAB) 0x804867c
0x0000000a (STRSZ) 3313 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000015 (DEBUG) 0x0
0x00000003 (PLTGOT) 0x8059114
0x00000002 (PLTRELSZ) 688 (bytes)
0x00000014 (PLTREL) REL
0x00000017 (JMPREL) 0x8049c58
0x00000011 (REL) 0x8049be0
0x00000012 (RELSZ) 120 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffe (VERNEED) 0x8049b60
0x6fffffff (VERNEEDNUM) 3
0x6ffffff0 (VERSYM) 0x8049a7e
0x00000000 (NULL) 0x0
Vous pouvez voir que INIT est égale à l'adresse de _init.
Le code pour frame_dummy et __ _ _ ne_global_ctors_aux est dans un ensemble de fichiers nommés crtbegin.o et crtend.o (et les variantes de ces noms). Ceux-ci font partie de la GCC. Ce code fait différentes choses nécessaires pour un programme C comme la mise en place de stdin, stdout, globales et variables statiques et d'autres choses.
Je crois que quelqu'un d'autre réponse déjà décrit ce que Windows ne.
Finalement, c'est le système d'exploitation. Il y a généralement un moyen entre le point d’entrée réel et la fonction principale, ceci est inséré par le compilateur.
Quelques détails (liés à Windows): Il existe un en-tête dans le fichier PE appelé IMAGE_OPTIONAL_HEADER
qui contient le champ AddressOfEntryPoint
, qui est à son tour l'adresse du premier octet de code du fichier qui sera réalisé.
Les appels de système d'exploitation principal. Il y aura une adresse dans la transférable, l'exécutable qui pointe à l'emplacement de la main (Voir l'Unix ABI pour plus d'informations).
Mais, qui appelle le système d'exploitation?
L'unité centrale de traitement, sur le "RESET" du signal, (qui est aussi affirmé à la mise sous tension), va commencer à rechercher dans certaines ROM à une adresse donnée (disons, 0xffff) pour les instructions.
Typiquement, il y aura une sorte d'instruction de saut pour le BIOS, qui obtient les puces de mémoire configurée, la base sur disque dur pilotes chargés, etc, etc. Ensuite, le Secteur de Démarrage du disque dur est en lecture, et la prochaine bootloader est lancée, qui charge le fichier contenant les informations de base sur la façon de lire, par exemple, une partition NTFS et comment lire le fichier du noyau lui-même. Le noyau de l'environnement sera mis en place, le noyau chargé, et puis et puis! - le noyau sera sauté à l'exécution.
Après tout ce dur travail a été fait, le noyau peut alors procéder à la charge de notre logiciel.
Le système d'exploitation appelle une fonction incluse dans le runtime C (CRT) et lié à votre exécutable. Appelons cela "CRT principal."
CRT principal fait un peu les choses, les deux plus importantes, au moins en C++, il est exécuté à travers un tableau global des classes C++ et appel à leurs constructeurs, et d'appeler votre fonction main() et donner sa valeur de retour de la coquille.
Le Visual C++ CRT principal fait un peu plus de choses, si ma mémoire est bonne. Il configure l'allocateur de mémoire, important si vous utilisez le Débogage CRT pour aider à trouver des fuites de mémoire ou de mauvaise accès. Il appelle également principal au sein d'une exception structurée gestionnaire de captures mauvais accès à la mémoire et autres plantages et les affiche.