驅動模組載入流程 module init

2021-09-28 13:43:37 字數 4347 閱讀 9014

kernel-4.4/init/main.c:905:    do_initcalls();

do_basic_setup

do_initcalls()

do_initcall_level  //for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)

do_one_initcall

fn();

alps$ grep -rsn "#define module_init(x)"  kernel-4.4/include/

kernel-4.4/include/linux/module.h:84:#define module_init(x)    __initcall(x);

kernel-4.4/include/linux/module.h

//module_init() will either be called during do_initcalls() (if builtin) or at module insertion time (if a module). 

#define module_init(x)    __initcall(x);

kernel-4.4\include\linux\init.h

#define __initcall(fn) device_initcall(fn)

#define device_initcall(fn)        __define_initcall(fn, 6)

/* initcalls are now grouped by functionality into separate 

* subsections. ordering inside the subsections is determined

* by link order. 

* for backwards compatibility, initcall() puts the call in 

* the device init subsection.

** the `id' arg to __define_initcall() is needed so that multiple initcalls

* can point at the same handler without causing duplicate-symbol build errors.

*/#define __define_initcall(fn, id) \

static initcall_t __initcall_##fn##id __used \

__attribute__((__section__(".initcall" #id ".init"))) = fn; \

lto_reference_initcall(__initcall_##fn##id)

initcall_t是乙個函式指標型別,定義也在init.h中 typedef int (*initcall_t)(void);

第一句的意思就是定義函式指標 static int *__initcall_fnid(void),將fn賦值給它。

而函式屬性__attribute__((__section__()))表示將函式指標放到section所表示的**段中。

第二句意思是將定義的函式指標放到.initcallid.init段中

每個模組呼叫:

kernel-4.4\drivers\input\ir_lf38h\remotectl.c

module_init(remotectl_mod_init);

module_exit(remotectl_mod_exit);

module_description("mtk keypad (ir) driver v0.4");

remotectl_mod_init

platform_driver_register

---------------------------------------------

關於mount_init(fn),core_initcall(fn),fs_initcall(fn)...巨集 

在閱讀核心原始碼時,會看到很多mount_init,core_initcall,fs_initcall這樣的巨集呼叫。檢視它們的定義,

都是定義在include\linux\init.h中。它們最終都是歸結於__define_initcall這個巨集。一開始我無法理解它們

的含義,不知道這些巨集所傳遞的函式fn是如何被呼叫執行的,經過一段時間的學習,我將對它的理解寫成此文,

希望大家指正。

__define_initcall巨集的定義為:

#define __define_initcall(level,fn,id) \

static initcall_t __initcall_##fn##id __used \

__attribute__((__section__(".initcall" level ".init"))) = fn

可以理解為函式fn是放在".initcall"level".init"section中的,其實就是將fn對應的函式指標置於其中。

level可以是0-7。也就是

.initcall0.init;

.initcall1.init;

.initcall2.init;

.initcall3.init;

.initcall4.init;

.initcall5.init;

.initcall6.init;

.initcall7.init;

關鍵是對這些節的理解。

可以檢視include\asm-generic\vmlinux.lds.**件,閱讀init_calls和init_calls_level巨集。

1)對於init_calls,此巨集在vmlinux.lds.s中被呼叫,是用來構造自定義的section的:

#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) = .;

1)對於init_calls_level:

#define init_calls_level(level) \

vmlinux_symbol(__initcall##level##_start) = .; \

*(.initcall##level##.init) \

*(.initcall##level##s.init) \

可以看到,從init_calls_level(0)-init_calls_level(7),將它們代入展開後,恰好構成了我們前面

所說的.initcall0.init-.initcall7.init節。同時還有__initcall0_start-__initcall7_start全域性

變數。看到這裡,可以總結出,mount_init(fn),fs_initcall(fn)等巨集中的fn就是放在init_calls所構建的節中。

而且這些節的起始位址就是__initcall0_start-__initcall7_start。

也就是.initcall0.init節的起始位址是__initcall0_start,凡是呼叫pure_initcall(fn)的(可以搜尋源**,會發現不止一處呼叫),其fn的位址就被放在此節中。其他依次類推。

好了,問題又來了,那麼那些函式fn是如何被呼叫的,它們就是在函式do_initcalls(init\main.c)中呼叫的。可以看到,全域性變數initcall_levels,其定義為:

static initcall_t *initcall_levels __initdata = ;

這不正是我們前面得出的起始位址嗎。do_initcalls函式會根據這些起始位址,遍歷每個起始位址所對應的

節(也就是.initcall0_init等)中的函式(可能不止乙個)。具體的遍歷細節,可以分析do_initcalls函式,相

關聯的函式還有do_initcall_level,do_one_initcall。

所以,當你在某個原始檔中看到mount_init(fn),fs_initcall(fn)等等時,就能夠知道這些fn最終是如何被

呼叫的了。

Apache模組載入流程

apache的模組載入包括兩部分 第一部分是prelink的模組,這部分模組已經鏈結好了 在modules.c中 ap declare data module ap prelinked modules 第二部分需要通過動態載入,1 在動態載入之前apache構建乙個模組鍊錶,首先將 prelink ...

MTK驅動 lcm驅動載入及呼叫流程

使用mt6739平台4.4核心,按下開機鍵,液晶開始顯示,從而進入lk載入lcm的階段 lk執行流程 開機執行 vendor mediatek proprietary bootable bootloader 目錄下 從preloader platform mt6739 src core main.c...

usb介面驅動載入流程分析

usb介面驅動載入流程分析 struct usb device driver usb generic driver struct bus type usb bus type 系統初始化時usb core會呼叫 retval usb register device driver usb generic...