include/linux/module.h
struct module:
struct module
{
// 用于在用戶空間傳入module對象時判斷傳入的結構是否有效
unsigned long size_of_struct; /* == sizeof(module) */
struct module *next;
// 指向本module的名稱,通常內核空間里申請的name內存位置都是緊跟在module{}結構后面的
const char *name;
// 本module{}結構的空間 + 緊接著這段內存申請的歸module{}結構使用的一部分空間
// size = sizeof(struct module) + sizeof(misc data)
unsigned long size;

// 模塊引用計數器,還沒搞清楚這里的pad是干什么用的
// i386中atomic_t的定義: typedef struct { volatile int counter; } atomic_t;
union
{
atomic_t usecount;
long pad;
} uc; /* Needs to keep its size - so says rth */

// 模塊當前狀態,已初始化/運行中/被移除/被訪問過等
unsigned long flags; /* AUTOCLEAN et al */

// 定義的內核模塊符號數
unsigned nsyms;
// 引用的模塊鏈表節點數,遍歷模塊依賴性時使用
unsigned ndeps;

// 符號表
struct module_symbol *syms;
// 記錄依賴的其他模塊的數組
struct module_ref *deps;
// 記錄引用該模塊的其他模塊的數組
struct module_ref *refs;
// 初始化和刪除模塊時調用的函數指針
int (*init)(void);
void (*cleanup)(void);
// 中斷向量表的入口和結束位置
const struct exception_table_entry *ex_table_start;
const struct exception_table_entry *ex_table_end;
#ifdef __alpha__
unsigned long gp;
#endif
/* Members past this point are extensions to the basic
module support and are optional. Use mod_member_present()
to examine them. */
// 這兩個指針維持一些模塊相關信息,方便卸載后再次裝載模塊時的配置
const struct module_persist *persist_start;
const struct module_persist *persist_end;
int (*can_unload)(void);
int runsize; /* In modutils, not currently used */
const char *kallsyms_start; /* All symbols for kernel debugging */
const char *kallsyms_end;
const char *archdata_start; /* arch specific data for module */
const char *archdata_end;
const char *kernel_data; /* Reserved for kernel internal use */
};
struct module_symbol:
保存目標代碼中的內核符號,讀取文件裝入模塊時通過這個數據結構將里面包含的符號信息讀入。
struct module_symbol
{
unsigned long value; // 入口地址
const char *name; // 內核符號名稱
};
struct module_ref:
注意這里dep和ref記錄的不對稱,應該可以看成是一個ref鏈表吧
module{} 中的deps數組分別指向了各個依賴的module_ref{}
struct module_ref
{
struct module *dep; /* "parent" pointer */
struct module *ref; /* "child" pointer */
struct module_ref *next_ref;
};
struct kernel_sym:
在sys_get_kernel_syms()中用到的結構,該函數將內核符號拷貝到用戶空間的kernel_sym{}中,從而可以在用戶態存放模塊信息。
struct kernel_sym
{
unsigned long value; // 內核符號地址
char name[60]; /* should have been 64-sizeof(long); oh well */
};
module.c中的一些函數先略去了,書上蠻詳細的
模塊的加載和卸載
insmod的任務:
從命令行中讀入模塊名,確定代碼所在文件的位置
計算需要的內存
執行系統調用create_module(),傳遞新模塊的名稱和大小
用QM_MODULES獲得所有已經鏈接模塊的模塊名
用QM_SYMBOL獲得內核符號表和已經鏈接到內核的模塊的符號表
使用這些信息重新定位該模塊文件中的代碼
在用戶空間分配內存,拷貝相關信息
調用sys_init_module(),傳遞上面創建的用戶態的內存區地址
釋放用戶態內存,結束
rmmod的任務:
用QM_MODULES和QM_REFS取得已經鏈接的模塊列表和依賴關系
調用delete_module
struct module:
























































struct module_symbol:
保存目標代碼中的內核符號,讀取文件裝入模塊時通過這個數據結構將里面包含的符號信息讀入。





struct module_ref:
注意這里dep和ref記錄的不對稱,應該可以看成是一個ref鏈表吧
module{} 中的deps數組分別指向了各個依賴的module_ref{}






struct kernel_sym:
在sys_get_kernel_syms()中用到的結構,該函數將內核符號拷貝到用戶空間的kernel_sym{}中,從而可以在用戶態存放模塊信息。





module.c中的一些函數先略去了,書上蠻詳細的
模塊的加載和卸載
insmod的任務:
從命令行中讀入模塊名,確定代碼所在文件的位置
計算需要的內存
執行系統調用create_module(),傳遞新模塊的名稱和大小
用QM_MODULES獲得所有已經鏈接模塊的模塊名
用QM_SYMBOL獲得內核符號表和已經鏈接到內核的模塊的符號表
使用這些信息重新定位該模塊文件中的代碼
在用戶空間分配內存,拷貝相關信息
調用sys_init_module(),傳遞上面創建的用戶態的內存區地址
釋放用戶態內存,結束
rmmod的任務:
用QM_MODULES和QM_REFS取得已經鏈接的模塊列表和依賴關系
調用delete_module