解密module init幕後的故事

2021-05-24 10:04:26 字數 1493 閱讀 4814

在linux底下寫過driver模組的對這個巨集一定不會陌生。module_init巨集在module巨集有沒有定義的情況下展開的內容是不同的,如果這個巨集沒有定義,基本上表明閣下的模組是要編譯進核心的(obj-y)。

1.在module沒有定義這種情況下,module_init定義如下:

#define module_init(x)        __initcall(x);

因為#define __initcall(fn)                               device_initcall(fn)

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

#define __define_initcall(level,fn,id) /

static initcall_t __initcall_##fn##id __used /

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

所以,module_init(x)最終展開為:

static initcall_t __initcall_##fn##id __used /

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

更直白點,假設閣下driver所對應的模組的初始化函式為int gpio_init(void),那麼module_init(gpio_init)實際上等於:

static initcall_t__initcall_gpio_init_6__used __attribute__((__section__(".initcall6.init"))) =gpio_init;

就是宣告一型別為initcall_t(typedef int (*initcall_t)(void))函式指標型別的變數__initcall_gpio_init_6並將gpio_init賦值與它。

這裡的函式指標變數宣告比較特殊的地方在於,將這個變數放在了一名為".initcall6.init"節中。接下來結合vmlinux.lds中的

.initcall.init : at(addr(.initcall.init) - (0xc0000000 -0x00000000))

以及do_initcalls:

static void __init do_initcalls(void)

那麼就不難理解閣下模組中的module_init中的初始化函式何時被呼叫了:在系統啟動過程中start_kernel()->rest_init()->kernel_init()->do_basic_setup()->do_initcalls()。

C 幕後的函式

乙個空類什麼時候不是空類?當c 編譯器通過它的時候。如果沒有宣告下列函式,體貼的編譯器會宣告它自己的版本。這些函式是 乙個拷貝建構函式,乙個賦值運算子,乙個析構函式,一對取址運算子。另外,如果你沒有宣告任何建構函式,它也將為你宣告乙個預設建構函式。所有這些函式都是公有的。換句話說,如果這麼寫 cla...

Windows Phone誕生的幕後故事

赫芬頓郵報 the huffington post 評價windows phone時說 太好了。網路雜誌 slate 認為,windows phone系統是智慧型手機系統中最漂亮的。而techcrunch則評價說 wp遠好於大多android手機。長久以來,微軟被視為缺乏創新的科技企業。科技部落格們...

C 異常的幕後(1)

每個人都知道良好的異常處理是困難的。在異常 生命期 的每個層面,出現這種情況的原因有許多 編寫異常安全的 是困難的,異常可能從不期望的位置丟擲 雙關語 理解設計不良的異常架構是複雜的,因為幕後發生了許多巫術,它是慢的 因為不正確地丟擲異常可能導致呼叫不可原諒的std terminate,它是危險的。...