Tout à fait.
Le __init est un raccourci pour dire que le code de la fonction appartient à la section .init.text, permettant ainsi de libérer cette mémoire après l'appel de ces fonctions qui ne seront plus utilisées.
Là où se joue l'ordre d'appel c'est à la définition du device_initcall(fonction).
/*
* Early initcalls run before initializing SMP.
*
* Only for built-in code, not modules.
*/
#define early_initcall(fn) __define_initcall("early",fn,early)
/*
* A "pure" initcall has no dependencies on anything else, and purely
* initializes variables that couldn't be statically initialized.
*
* This only exists for built-in code, not for modules.
*/
#define pure_initcall(fn) __define_initcall("0",fn,0)
Le level définit l'ordre d'appel. Plus il est petit, plus l'appel se fait au début.
On commence par les early_initcall (avant que le multiprocesseur soit activé).
Ensuite viennent les fonctions du coeur du noyau, puis les éléments relatifs à l'architecture, puis les sous-systèmes, puis le système de fichier, etc....
Ce qui donnera une section .initcall0.init pour les pure_initcall, .initcall1.init pour le coeur du noyau etc....
Et voilà, les pointeurs de fonctions seront regroupés par sections et rangés dans le bon ordre :-)
[^] # Re: Fort intéressant...
Posté par fweisbec . En réponse à la dépêche L'évolution de Fastboot. Évalué à 6.
Le __init est un raccourci pour dire que le code de la fonction appartient à la section .init.text, permettant ainsi de libérer cette mémoire après l'appel de ces fonctions qui ne seront plus utilisées.
Là où se joue l'ordre d'appel c'est à la définition du device_initcall(fonction).
Voici un extrait de include/linux/init.h
#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
/*
* Early initcalls run before initializing SMP.
*
* Only for built-in code, not modules.
*/
#define early_initcall(fn) __define_initcall("early",fn,early)
/*
* A "pure" initcall has no dependencies on anything else, and purely
* initializes variables that couldn't be statically initialized.
*
* This only exists for built-in code, not for modules.
*/
#define pure_initcall(fn) __define_initcall("0",fn,0)
#define core_initcall(fn) __define_initcall("1",fn,1)
#define core_initcall_sync(fn) __define_initcall("1s",fn,1s)
#define postcore_initcall(fn) __define_initcall("2",fn,2)
#define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)
#define arch_initcall(fn) __define_initcall("3",fn,3)
#define arch_initcall_sync(fn) __define_initcall("3s",fn,3s)
#define subsys_initcall(fn) __define_initcall("4",fn,4)
#define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s)
#define fs_initcall(fn) __define_initcall("5",fn,5)
#define fs_initcall_sync(fn) __define_initcall("5s",fn,5s)
#define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs)
#define device_initcall(fn) __define_initcall("6",fn,6)
#define device_initcall_sync(fn) __define_initcall("6s",fn,6s)
#define late_initcall(fn) __define_initcall("7",fn,7)
#define late_initcall_sync(fn) __define_initcall("7s",fn,7s)
Le level définit l'ordre d'appel. Plus il est petit, plus l'appel se fait au début.
On commence par les early_initcall (avant que le multiprocesseur soit activé).
Ensuite viennent les fonctions du coeur du noyau, puis les éléments relatifs à l'architecture, puis les sous-systèmes, puis le système de fichier, etc....
Ce qui donnera une section .initcall0.init pour les pure_initcall, .initcall1.init pour le coeur du noyau etc....
Et voilà, les pointeurs de fonctions seront regroupés par sections et rangés dans le bon ordre :-)