怎樣做網(wǎng)站開發(fā)搜索優(yōu)化seo
linux版本:4.19
module_init()與module_exit()用于驅(qū)動的加載,分別是驅(qū)動的入口與退出函數(shù)
- module_init():內(nèi)核啟動時或動態(tài)插入模塊時調(diào)用
- module_exit():驅(qū)動移除時調(diào)用
本篇文章介紹module_init()
module_init()
module_init()是驅(qū)動的入口函數(shù),該函數(shù)定義在include\linux\module.h文件
/*** module_init() - driver initialization entry point* @x: function to be run at kernel boot time or module insertion** module_init() will either be called during do_initcalls() (if* builtin) or at module insertion time (if a module). There can only* be one per module.*/
#define module_init(x) __initcall(x);
__initcall(x)函數(shù)定義在include\linux\init.h文件里面
#define __initcall(fn) device_initcall(fn)
device_initcall(fn)定義也在include\linux\init.h文件里面
#define device_initcall(fn) __define_initcall(fn, 6)
__define_initcall(fn, 6)定義也在include\linux\init.h文件里面
#define __define_initcall(fn, id) ___define_initcall(fn, id, .initcall##id)
___define_initcall(fn, id, .initcall##id)定義也在include\linux\init.h文件里面
/** 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.** Initcalls are run by placing pointers in initcall sections that the* kernel iterates at runtime. The linker can do dead code / data elimination* and remove that completely, so the initcall sections have to be marked* as KEEP() in the linker script.*/#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
#define ___define_initcall(fn, id, __sec) \__ADDRESSABLE(fn) \asm(".section \"" #__sec ".init\", \"a\" \n" \"__initcall_" #fn #id ": \n" \".long " #fn " - . \n" \".previous \n");
#else
#define ___define_initcall(fn, id, __sec) \static initcall_t __initcall_##fn##id __used \__attribute__((__section__(#__sec ".init"))) = fn;
#endif
綜上module_init調(diào)用順序如下:
module_init()--->__initcall()--->device_initcall()--->__define_initcall()--->___define_initcall()
對___define_initcall()函數(shù)進行分析
首先了解一下#與##的作用
符號 | 作用 | 舉例 |
---|---|---|
## | “##”符號可以是連接的意思 | 例如initcall_##fn##id為initcall_fnid,假設(shè)fn為fbmem_init,id=6時,initcall_##fn##id為initcall_fbmem_init6 |
# | "#"符號可以是字符串的意思 | 例如#id為“id”,id=6時,#id為“6” |
所以module_init(fbmem_init)函數(shù),相當于
static initcall_t __initcall_fbmem_init6 __used __attribute__((__section__(".initcall6.init"))) =fbmem_init
這行代碼定義了一個靜態(tài)變量__initcall_fbmem_init6,變量類型為initcall_t(是一個函數(shù)指針類型,用于表示內(nèi)核的初始化函數(shù)),__used 用于告訴編譯器不要將“__initcall_fbmem_Init6”變量視為未使用的變量,避免編譯器優(yōu)化移除它。
attribute((section(“.initcall6.init”))),編譯器指令,告訴編譯器將“__initcall_fbmem_init6”變量放置在‘.initcall6.init’的代碼段中(這個代碼段通常用于存放內(nèi)核的初始化函數(shù),在啟動的時候按順序執(zhí)行,.initcall1.init、.initcall2.init 。。。)
‘= fbmem_init’ 這將’__initcall_fbmem_init6’初始化為指向‘fbmem_init’函數(shù)的指針。
??總之,這段代碼的作用是將‘fbmem_init’函數(shù)注冊為一個初始化函數(shù),使其在內(nèi)核啟動的時候執(zhí)行。
對于編譯成模塊,執(zhí)行sudo insmod的時候,是如何加載的,等我知道后再來寫