Le noyau a-t-il une fonction main ()? [fermé]

52

J'apprends les pilotes de périphérique et la programmation du noyau. Selon le livre de Jonathan Corbet, il n'y a aucune main()fonction dans les pilotes de périphérique.

J'ai donc deux questions:

  • Pourquoi n'avons-nous pas besoin d'une main()fonction dans les pilotes de périphérique?
  • Le noyau lui-même a-t-il une main()fonction?

Quelqu'un peut m'expliquer cela?

Quelqu'un
la source
1
Également demandé par le même utilisateur ici: stackoverflow.com/q/18266063/827263
Keith Thompson
@ KeithThompson ... Oui ... Juste parce que je n'ai pas eu la réponse à ce que je voulais, je l'ai posée ici.
quelqu'un
@Shadur ... en tout cas maintenant il est sur le point de fermer ... Et je n'ai pas le privilège d'émigrer que ...
quelqu'un
Cela aurait dû être fermé dans l'autre sens, celui-ci a beaucoup plus de points de vue :-)
Ciro Santilli a écrit:

Réponses:

82

Dans les programmes d’espace utilisateur, main()est le point d’entrée du programme appelé par le code d’initialisation de la bibliothèque lorsque le fichier binaire est exécuté. Le code du noyau n'a pas le luxe de s'appuyer sur libc, car libc lui-même repose sur l'interface syscall du noyau pour l'allocation de mémoire, les E / S, la gestion des processus, etc.

Cela dit, l’équivalent de main()dans le code du noyau est start_kernel(), qui est appelé par le chargeur de démarrage après avoir chargé l’image du noyau, l’a décompressée en mémoire et configuré le matériel essentiel ainsi que la pagination de la mémoire. start_kernel()effectue la majeure partie de la configuration du système et engendre finalement le processus init.

Le point d’entrée des modules du noyau Linux est une fonction init enregistrée auprès du noyau en appelant la module_init()macro. La fonction init du module enregistré est ensuite appelée par le code du noyau via la do_initcalls()fonction au démarrage du noyau.

Thomas Nyman
la source
11
Merci de reconnaître le but réel de la mainméthode en C. (C’est une idée fausse bien trop répandue selon laquelle le système d’exploitation appelle directement main, ce qui n’est pas le cas et est encore moins le cas, par exemple, en C ++.) I ' d vous donner un autre upvote si je pouvais juste pour ça.
un CVn
1
@Thomas ... Merci pour cette excellente réponse ....
quelqu'un d'
17

Le noyau n'a pas de mainfonction. mainest un concept du langage C. Le noyau est écrit en C et en assembleur. Le code d'entrée du noyau est écrit par assembly.

La séquence de démarrage est organisée comme suit:

  1. Le BIOS charge généralement un chargeur de démarrage à partir d'un périphérique de bloc de démarrage. Un chargeur de démarrage populaire actuellement est grub.
  2. Grub charge une image du noyau dans la RAM, possible avec un périphérique racine initial ( initrd). Ensuite, le code à une adresse est exécuté.
  3. L'image du noyau contient certains modules du noyau, par exemple: modules de système de fichiers, pilotes de périphériques. L'image du noyau utilise le module de système de fichiers pour monter le système de fichiers racine. Maintenant, le noyau peut charger et exécuter tous les modules du noyau à partir du disque.
  4. Le noyau exécute les tâches d'initialisation. Par exemple: traversez le bus PCI et recherchez tous les périphériques PCI, initialisez tous les pilotes de périphérique.
  5. Enfin, le noyau crée les processus 0 et 1 ( initprocessus), fait passer le contexte de la CPU de l’anneau 0 à l’anneau 3 et démarre le processus init (l’identificateur de processus est 1). Maintenant, le démarrage du noyau est terminé!
  6. Le initprogramme exécute tous les scripts d'initialisation. Tous les services sont démarrés. Shell s'appelle. Les utilisateurs peuvent se connecter.

La mainfonction est une fonction C. En réalité, la méthode principale n’est pas le point d’entrée des programmes C. Le runtime C appelle plusieurs fonctions auparavant main. GCC a une fonctionnalité d'extension: les constructeurs. Les fonctions déclarées "constructeur" sont appelées avant main.

Par exemple:

/* This should not be used directly. Use block_init etc. instead. */ 
#define module_init(function, type) \
    static void _attribute__((constructor)) do_qemu_init ## function(void) { \
    register_module_init(function, type); \
} 

Cette macro provient du projet qemu.

Edward Shen
la source
La méthode principale est la méthode ac.La méthode principale en réalité n'est pas l'entrée de c program.C Le temps d'exécution a appelé de nombreuses méthodes avant la méthode principale.
Edward Shen
eh bien, bios charge généralement un chargeur de démarrage, et ce dernier charge une image du noyau (et éventuellement un initrd). Le code du noyau est dans l'image du noyau, pas initrd
Stéphane Chazelas
GCC a une fonctionnalité d'extension: constructeur. La déclaration de méthode "constructeur" est appelée avant la méthode principale. Par exemple: / * Ceci ne devrait pas être utilisé directement. Utilisez block_init etc. à la place. * / #define module_init (fonction, type) \ static void _attribute __ ((constructeur)) do_qemu_init ## function (void) {\ register_module_init (fonction, type); \}
Edward Shen
1
initrd.img N’EST PAS l’image du noyau. C'est un ensemble de modules chargés par le noyau au démarrage. Les images du noyau portent généralement des noms commençant par "vmlinuz" mais diffèrent de distro en distro.
goldilocks
3
Cette réponse est remplie de "tout est un PC / Linux / i86" et il démarre de cette façon et le noyau est de cette façon ... Pourquoi tout le monde pense-t-il que c'est la seule façon possible dans le monde?
Jens
9

Il existe par exemple une fonction main () dans arch / x86 / boot / main.c pour préparer le système à passer du mode réel au mode protégé, mais les autres architectures ne disposent pas d'un tel code. Voici un bon aperçu du fonctionnement du démarrage du noyau Linux 2.6.x sur une plate-forme x86. Cela vaut vraiment la peine de le lire.

Selon le document HOWTO relatif au développement du noyau Linux , le noyau Linux est

un environnement C autonome, sans dépendance de la bibliothèque C standard, de sorte que certaines parties de la norme C ne sont pas prises en charge.

ce qui selon la norme C BTW signifie que

Il est défini par l'implémentation si un programme dans un environnement autonome est requis pour définir une fonction "principale".

dsmsk80
la source