Répertoire d'articles
-
- Comment lire efficacement le code du noyau
- 1 Trouvez le point d'entrée de conduite (la montagne a une petite bouche, comme s'il y avait de la lumière)
- 2 clarifier le contexte principal (sera le sommet du Ling Ling, un coup d'œil sur les petites montagnes)
- 3 Fonctions spécifiques en profondeur (le ruisseau retourne dans la vallée, et il n'y a pas de route, du coup il y a une ou deux fleurs de prunier)
Comment lire efficacement le code du noyau
Dans une large mesure, le développement du noyau n'est pas un processus de réinvention de la "roue", mais de comprendre et de réutiliser le plus possible le cadre de conception du noyau existant, puis de se référer à des modules fonctionnels similaires pour ajouter ou réécrire une fonction requise. Ce n'est qu'après l'intégration du cadre général du noyau et de certains sous-systèmes que nous pourrons nous reposer sur les épaules de géants pour améliorer le cadre lui-même et parvenir à une innovation indépendante. Si vous surestimez une "innovation indépendante" inutile, cela peut aggraver la maintenabilité du noyau, et le résultat final ne vaudra pas la perte.
Donc, cette fois, je vais le partager sur la façon de lire efficacement le code du pilote du noyau:
1 Trouvez le point d'entrée de conduite (la montagne a une petite bouche, comme s'il y avait de la lumière)
Si la forêt est pleine d'eau, il y aura une montagne, et la montagne a une petite bouche, comme s'il y avait de la lumière
1.1 Entrée du pilote de périphérique
La lecture du code du pilote du noyau consiste d'abord à trouver sa fonction d'entrée brillante. Prenons un module de noyau relativement indépendant comme exemple. Dans la plupart des cas, si le nom du modname
module est , alors la fonction d'entrée du module est modname_init()
. La fonction de saisie du module est généralement utilisée module_init(modname_init)
pour la déclaration.
#define module_init(x) __initcall(x); //include/linux/init.h
1.2 Entrée du sous-système
Une fois l'analyse des options du noyau terminée, l'initialisation de chaque sous-système entre dans la deuxième partie - l'appel de la fonction d'entrée. En général, les sous-systèmes tels que USB et PCI auront une subsys_initcall
entrée nommée , si vous les choisissez comme point d'entrée pour étudier le noyau, veuillez d'abord le trouver.
1.3 Où est donc l'entrée du noyau lui-même?
L'entrée initiale (la première entrée) est liée à l'architecture, dans le code du langage assembleur;
tandis que l'entrée générale (la deuxième entrée) est indépendante de l'architecture, et elle est en fait à l' init/main.c
intérieur du langage C. start_kernel()
C'est do_initcalls()
la fonction que nous devons rechercher. , Exécute toutes les module_init()
fonctions déclarées dans cette fonction
start_kernel
-> rest_init();
-> kernel_thread(kernel_init, NULL, CLONE_FS);
-> kernel_init()
-> kernel_init_freeable();
-> do_basic_setup();
-> do_initcalls();
2 clarifier le contexte principal (sera le sommet du Ling Ling, un coup d'œil sur les petites montagnes)
Nous devons être en mesure de trier la trame initiale lorsque nous initialisons la fonction.
Par exemple, MMC
lors de l'initialisation du sous-système, le code est comme un arbre. Nous devons d'abord trouver le tronc, puis déterminer combien de branches il y a sur le tronc, puis rechercher des feuilles significatives sur une branche d'intérêt, au lieu d'en rencontrer une. La branche racine, nous nous sommes dépêchés de découvrir toutes les feuilles, lorsque ces dernières nous tomberons dans la confusion de "ne pas connaître le vrai visage du mont Lu, seulement en étant dans cette montagne", notre poursuite est "d'être le sommet de la montagne, voir tout le monde Les "petites montagnes" sont transparentes.
- Bus, appareil, chauffeur
En développement, nous n'écrivons pas vraiment de modèle de bus, si nous nous concentrons sur des fonctions spécifiques, nous devons nous concentrer sur le probe
contenu des fonctions métiers pilotées par les périphériques que nous effectuons dans le développement.
entité | Caractéristiques |
---|---|
équipement | Décrivez l'adresse de base, le numéro d'interruption, l'horloge, le DMA, la réinitialisation et d'autres informations |
conduire | Fonctions périphériques complètes, telles que la réception et l'envoi de paquets par carte réseau, l'enregistrement et la lecture de la carte son, la lecture et l'écriture sur carte SD ... |
autobus | Terminez l'association de l'appareil et du pilote |
Ensuite, le processus d'appariement des trois d'entre eux n'est pas au centre du développement, nous pouvons étudier dans le futur, et l'objectif est encore à analyser probe
.
Jetons d'abord un coup d'œil au processus de correspondance, et nous pouvons voir la complexité de la correspondance:
3 Fonctions spécifiques en profondeur (le ruisseau retourne dans la vallée, et il n'y a pas de route, du coup il y a une ou deux fleurs de prunier)
Les ruisseaux doux et tortueux (fonction d'entraînement) s'attardent dans la vallée (le noyau interne).
Ici, nous devons nous concentrer sur ce que nous voulons étudier;
Prenons l'exemple de MMC:
les fonctions sur lesquelles nous devons nous concentrer sont:
- Détection d'insertion
- Réinitialiser
- Détection de type
- Vérification de la tension
- Acquisition CID
- Attendre