1 / 26

Linux Kernel Module

Linux Kernel Module. 中科院计算所软件室向泓 2000.11. 目录. 概述 LKM 的实现 LKM 编程. 概述. Linux 是 一个单体内核的操作系统; Kernel Module 是对内核的扩充,可动态加载和卸载;. LKM 的实现. 连接和载入( Linking & Loading) ,ELF 格式 相关内核数据结构,系统调用, kerneld & kmod modutils. Linking & Loading. 三个基本要求: 符号解析( Symbol Resolution) ; 重定位( Relocation) ;

Télécharger la présentation

Linux Kernel Module

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Linux Kernel Module 中科院计算所软件室向泓 2000.11

  2. 目录 • 概述 • LKM的实现 • LKM编程

  3. 概述 • Linux是一个单体内核的操作系统; • Kernel Module是对内核的扩充,可动态加载和卸载;

  4. LKM的实现 • 连接和载入(Linking & Loading),ELF格式 • 相关内核数据结构,系统调用,kerneld & kmod • modutils

  5. Linking & Loading • 三个基本要求: • 符号解析(Symbol Resolution); • 重定位(Relocation); • 程序载入(Program Loading); • Linker和Loader的功能划分: • Linker:符号解析,重定位; • Loader:重定位,程序载入;

  6. 文件格式 • COM; • A.OUT; • EXE; • COFF; • ELF; • PE; • OMF;

  7. Executable and Linkable Format • ELF是Linux的标准二进制文件格式; • 更方便的实现共享库和动态连接; • Sections & Segments • SHT_PROGBITS • SHT_SYMTAB • SHT_STRTAB • SHT_REL(SHT_RELA)

  8. struct module(1) • struct module { • unsigned long size_of_struct; • struct module *next; • const char * name; • unsigned long size; • union { • atomic_t usecount; • long pad; • } uc; • unsigned long flags; • unsigned nsyms; • unsigned ndeps;

  9. struct module(2) • 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; • const struct module_persist *persist_start; • const struct module_persist *persist_end; • int (*can_unload)(void); • };

  10. sys_create_module() • sys_create_module(const char *name_user, size_t size) • 为模块数据结构和模块映象分配核心空间; • 将模块数据结构加入module_list表头;

  11. sys_init_module() • sys_init_module(const char *name_user, struct module *mod_user) • 检查模块映象的合法性; • 更新模块依赖链表;

  12. struct module_ref • struct module_ref { • struct module *dep; • struct module *ref; • struct module_ref *next_ref; • };

  13. sys_delete_module() • sys_delete_module(const char *name_user) • 模块的refs链为空,宏__MOD_IN_USE()返回0,此时可卸载指定模块; • #define __MOD_IN_USE(mod) (mod_member_present((mod), can_unload) && (mod)->can_unload ? (mod)->can_unload() : atomic_read(&(mod)->uc.usecount)) • 更新模块依赖链表和模块链表;

  14. sys_query_module() • sys_query_module(const char name_user, int which, char *buf, size_t bufsize, size_t *ret) • QM_MODULES:返回所有已加载模块名; • QM_DEPS:返回指定模块依赖的所有模块名; • QM_REFS:返回所有引用指定模块的模块名; • QM_SYMBOLS:返回指定模块提供的所有符号名及其地址; • QM_INFO:返回指定模块的地址,大小和状态信息;

  15. sys_get_kernel_syms() • sys_get_kernel_syms(struct kernel_sym *table) • 已过时的系统调用; • 相当于sys_query_module(NULL, QM_SYMBOLS, ...)的功能;

  16. kerneld • 在内核版本1.3.57中引入,存在于版本2.0和2.1中,在2.2及以上版本中被kmod取代; • 分为内核级和用户级两部分; • 内核级:request_module(), release_module(); • 用户级:kerneld守护进程,根据请求执行modprobe,定期卸载空闲模块;

  17. kmod • 是kerneld的替代; • 无须用户级守护进程; • request_module()启动一个核心线程,该线程执行modprobe加载需要的模块; • 不能自动卸载空闲模块;

  18. modutils • ksyms:sys_query_module(…,QM_SYMBOLS,…) • lsmod:sys_query_module(…,QM_MODULES,…) • modinfo:sys_query_module(…,QM_INFO,…) • rmmod:sys_delete_module() • depmod:分析模块树,构造模块依赖文件; • modprobe:根据依赖文件,加载模块栈; • genksyms:构造带版本信息的内核符号; • insmod:构造模块映象并加载;

  19. insmod • 检查版本是否匹配(kernel_version和using_checksums); • 利用内核符号解析模块中的未定义引用; • __this_module; • 处理模块参数; • 构造模块依赖链表;构造__ksymtab,若尚未存在,用模块符号填充; • 重定位; • 构造模块映象,加载;

  20. LKM编程 • Hello World • 版本控制 • 输出符号 • 模块参数 • 调试技术

  21. Hello World • hello.c: • #include <linux/kernel.h> • #include <linux/module.h> • int init_module() { printk(“hello, world!\n”; return 0; } • void cleanup_module() { printk(“bye, world!\n”); } • $ gcc -c -D__KERNEL__ -DMODULE hello.c • 使用多个.c文件: • #define __NO_VERSION__ • $ ld -r -o hello.o init.o clean.o

  22. 版本控制 • 最早的版本控制简单的比较内核版本号和模块符号kernel_version的值; • 新的版本控制比较二进制接口的一致性; • 某符号的二进制接口定义为该符号的定义CRC校验和; • 仅当内核和模块都支持时此新方式才起作用,否则沿用旧的版本控制方式; • #define MODVERSIONS • #include <linux/modversions.h>

  23. 输出符号 • #define EXPORT_SYMTAB • EXPORT_NO_SYMBOLS; • EXPORT_SYMBOL(name); • EXPORT_SYMBOL_NOVERS(name);

  24. 模块参数 • MODULE_PARM(name, type); • type:”min-maxT”; • T:s,c,b,h,i,l

  25. 调试技术 • printk • 利用/proc文件系统或ioctl; • ksymoops • 使用调试器 • gdb • kdebug • 远程调试

  26. Thank You!

More Related