linux kernel中的module_init/initcall代码导读
文章目錄
- 1、initcall的分類
- 2、__initcall的調用
- 3、module_driver/module_i2c_driver
★★★ 友情鏈接 : 個人博客導讀首頁—點擊此處 ★★★
1、initcall的分類
在kernel/include/linux/module.h中
#define module_init(x) __initcall(x);在kernel/include/linux/init.h中,定義了一堆宏
#define pure_initcall(fn) __define_initcall(fn, 0) #define core_initcall(fn) __define_initcall(fn, 1) #define core_initcall_sync(fn) __define_initcall(fn, 1s) #define postcore_initcall(fn) __define_initcall(fn, 2) #define postcore_initcall_sync(fn) __define_initcall(fn, 2s) #define arch_initcall(fn) __define_initcall(fn, 3) #define arch_initcall_sync(fn) __define_initcall(fn, 3s) #define subsys_initcall(fn) __define_initcall(fn, 4) #define subsys_initcall_sync(fn) __define_initcall(fn, 4s) #define fs_initcall(fn) __define_initcall(fn, 5) #define fs_initcall_sync(fn) __define_initcall(fn, 5s) #define rootfs_initcall(fn) __define_initcall(fn, rootfs) #define device_initcall(fn) __define_initcall(fn, 6) #define device_initcall_sync(fn) __define_initcall(fn, 6s) #define late_initcall(fn) __define_initcall(fn, 7) #define late_initcall_sync(fn) __define_initcall(fn, 7s)#define __initcall(fn) device_initcall(fn)其實對應的就是就是".initcall0.init ~ .initcall7.init"的__section__段
#define __define_initcall(fn, id) \static initcall_t __initcall_##fn##id __used \__attribute__((__section__(".initcall" #id ".init"))) = fn; \LTO_REFERENCE_INITCALL(__initcall_##fn##id)我們再總結下,module_init(xxx_init)其實就是在.initcall6.init的__section__段中分配一個地址,指向xxx_init函數(shù)
而__section__段的定義在vmlinux.ld.S的INIT_CALLS中
.init.data : {
INIT_DATA
INIT_SETUP(16)
INIT_CALLS
CON_INITCALL
SECURITY_INITCALL
INIT_RAM_FS
}
INIT_CALLS是定義在vmlinux.ld.h的一個宏
#define INIT_CALLS_LEVEL(level) \VMLINUX_SYMBOL(__initcall##level##_start) = .; \*(.initcall##level##.init) \*(.initcall##level##s.init) \ #define INIT_CALLS \VMLINUX_SYMBOL(__initcall_start) = .; \*(.initcallearly.init) \INIT_CALLS_LEVEL(0) \INIT_CALLS_LEVEL(1) \INIT_CALLS_LEVEL(2) \INIT_CALLS_LEVEL(3) \INIT_CALLS_LEVEL(4) \INIT_CALLS_LEVEL(5) \INIT_CALLS_LEVEL(rootfs) \INIT_CALLS_LEVEL(6) \INIT_CALLS_LEVEL(7) \VMLINUX_SYMBOL(__initcall_end) = .;這些section段的地址是:
__initcall0_start,
__initcall1_start,
__initcall2_start,
__initcall3_start,
__initcall4_start,
__initcall5_start,
__initcall6_start,
__initcall7_start,
2、__initcall的調用
在kernel/init/main.c中:
依次循環(huán)調用了這些section段的函數(shù)
static initcall_t *initcall_levels[] __initdata = {__initcall0_start,__initcall1_start,__initcall2_start,__initcall3_start,__initcall4_start,__initcall5_start,__initcall6_start,__initcall7_start,__initcall_end, };static void __init do_initcall_level(int level) {initcall_t *fn;strcpy(initcall_command_line, saved_command_line);parse_args(initcall_level_names[level],initcall_command_line, __start___param,__stop___param - __start___param,level, level,NULL, &repair_env_string);for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)do_one_initcall(*fn); }static void __init do_initcalls(void) {int level;for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)do_initcall_level(level); }int __init_or_module do_one_initcall(initcall_t fn) {int count = preempt_count();int ret;char msgbuf[64];if (initcall_blacklisted(fn))return -EPERM;if (initcall_debug)ret = do_one_initcall_debug(fn);elseret = fn();msgbuf[0] = 0;if (preempt_count() != count) {sprintf(msgbuf, "preemption imbalance ");preempt_count_set(count);}if (irqs_disabled()) {strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf));local_irq_enable();}WARN(msgbuf[0], "initcall %pF returned with %s\n", fn, msgbuf);return ret; } static bool __init_or_module initcall_blacklisted(initcall_t fn) {struct list_head *tmp;struct blacklist_entry *entry;char *fn_name;fn_name = kasprintf(GFP_KERNEL, "%pf", fn);if (!fn_name)return false;list_for_each(tmp, &blacklisted_initcalls) {entry = list_entry(tmp, struct blacklist_entry, next);if (!strcmp(fn_name, entry->buf)) {pr_debug("initcall %s blacklisted\n", fn_name);kfree(fn_name);return true;}}kfree(fn_name);return false; }3、module_driver/module_i2c_driver
在device.h中:
#define module_driver(__driver, __register, __unregister, ...) \ static int __init __driver##_init(void) \ { \return __register(&(__driver) , ##__VA_ARGS__); \ } \ module_init(__driver##_init); \ static void __exit __driver##_exit(void) \ { \__unregister(&(__driver) , ##__VA_ARGS__); \ } \ module_exit(__driver##_exit);在i2c.h中
#define module_i2c_driver(__i2c_driver) \module_driver(__i2c_driver, i2c_add_driver, \i2c_del_driver) 《新程序員》:云原生和全面數(shù)字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的linux kernel中的module_init/initcall代码导读的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [专栏目录]-Android专栏目录
- 下一篇: Android keystore/Key