实验五内核模块设计实验.docx
《实验五内核模块设计实验.docx》由会员分享,可在线阅读,更多相关《实验五内核模块设计实验.docx(16页珍藏版)》请在三一办公上搜索。
1、实验五内核模块设计实验实验五 内核模块设计实验 文章由网提供现代的Linux内核是具有微内核特点的宏内核。Linux内核作为一个大程序在内核空间运行。太多的设备驱动和内核功能集成在内核中,内核过于庞大。 Linux内核引入内核模块机制。通过动态加载内核模块,使得在运行过程中扩展内核的功能。不需要的时候,卸载该内核模块。 内核模块 内核模块是一种没有经过链接,不能独立运行的目标文件,是在内核空间中运行的程序。经过链接装载到内核里面成为内核的一部分,可以访问内核的公用符号。 内核模块可以让操作系统内核在需要时载入和执行,在不需要时由操作系统卸载。它们扩展了操作系统内核的功能却不需要重新启动系统。
2、如果没有内核模块,我们不得不一次又一次重新编译生成单内核操作系统的内核镜 像来加入新的功能。这还意味着一个臃肿的内核。 内核模块是如何被调入内核工作的? 当操作系统内核需要的扩展功能不存在时,内核模块管理守护进程kmod执行modprobe去加载内核模块。 modprobe遍历文件/lib/modules/version/modules.dep 来判断是否有其它内核模块需要在该模块加载前被加载。 最后modprobe调用insmod先加载被依赖的模块,然后加载该被内核要求的模块。 内核模块是如何被调入内核工作的? Insmod将调用init_module系统调用,传入参数 (Module.c)
3、Sys_init_module系统调用检查权限后,并查找modules链表,验证模块未被链接。然后分配一个module结构体变量描述该内核模块。 如果定义了模块的init方法,则执行init方法。 模块机制的特点: 减小内核映像尺寸,增加系统灵活性; 节省开发时间;修改内核,不必重新编译整个内核。 模块的目标代码一旦被链入内核,作用和静态链接的内核目标代码完全等价。 最简单的内核模块 任一个内核模块需要包含linux/module.h 初始化函数init_module,在模块加载到内核时被调用。init_module向内核注册模块的功能,申请需要的资料等初始化工作。 卸载函数cleanup_m
4、odule ,在内核模块被卸载时被调用,干一些收尾清理的工作,撤消任何初始化函数init_module做的事,保证内核模块可以被安全的卸载。 printk( )函数 printk 函数在 Linux 内核中定义并且对模块可用,为内核提供日志功能, 记录内核信息或用来给出警告。与标准 C 库函数 printf 的行为相似。 每个printk 声明都会带一个优先级。内核总共定义了八个优先级的宏, 在linux/kernel.h中定义。若你不指明优先级,DEFAULT_MESSAGE_LOGLEVEL这个默认优先级将被采用。 信息存在在内核消息缓冲区中,并被定时的添加到文件 /var/log/mes
5、sages,可直接查看,或者用命令dmesg查看。在Xwindows下的终端insmod一个模块,日志信息只会记录在日志文件中,而不在终端打印。 从内核Linux 2.4之后,可以为模块的“初始化”和“卸载”函数起任意的名字。不再必须使用 init_module和cleanup_module的名字。 通过宏 module_init和module_exit实现。这些宏在linux/init.h中定义。 module_init(hello_2_init); module_exit(hello_2_exit); 函数必须在宏的使用前定义,否则编译会报错。 关于_init和_exit宏 如果该模块被编
6、译进内核,而不是动态加载,则宏 _init的使用会在初始化完成后丢弃该函数并收回所占内存。 如果该模块被编译进内核,宏_exit将忽略“清理收尾”的函数。 这些宏在头文件linux/init.h定义,用来释放内核占用的内存。例如启动时看到的信息“Freeing unused kernel memory: 236k freed”,正是内核释放这些函数所占用空间时的打印信息。 内核模块证书和内核模块文档说明 2.4内核后,引入识别代码是否在GPL许可下发布的机制 。在使用非公开的源代码产品时会得到警告。 通过宏MODULE_LICENSE(“GPL”),设置模块遵守GPL证书,取消警告信息。 宏M
7、ODULE_DESCRIPTION用来描述模块的用途。 宏MODULE_AUTHOR用来声明模块的作者。 宏MODULE_SUPPORTED_DEVICE 声明模块支持的设备。 这些宏都在头文件linux/module.h定义。使用这些宏只是用来提供识别信息。 准备工作 顺利编译并且加载第一个“hello world”模块有时会比较困难。 保证系统具备正确的编译器、模块工具、以及其他必要工具。内核目录 Documentation/Changes 列出了需要的工具版本。用错误的工具版本建立一个内核,可能导致一些奇怪复杂的问题。 通常芯片公司的SDK包会告诉你使用什么版本的交叉工具链去完成,并提供
8、相应的工具链。 准备好系统平台所对应的内核源代码 配置并构建好平台对应的2.6内核源代码。 2.6 内核使用kbuild构建系统配置编译,kbuild构建系统可用于编译自定义的内核模块。 编译过程首先会到内核源码目录下,读取顶层的Makefile文件,然后再编译模块源码,连接生成的内核模块后缀为.ko 在内核源代码目录下: make menuconfig,使得配置跟目标平台一致 make 编写内核模块的makefile 内核Makefile提供的obj-m表示对象文件编译成可加载的内核模块 Hello-1.c的Makefile文件 obj-m += hello-1.o 表明有一个模块要从目标文
9、件 hello-1.o 建立,kbuild从该目标文件建立内核模块hello-1.ko。 编译内核模块的命令 make -C 内核源代码路径 M=模块所在路径 modules make -C /lib/modules/uname -r/build M=$PWD modules 改变目录到用 -C 选项提供的内核源码目录,make读取内核的makefile,并编译M所指定路径下的内核模块源代码。 内核模块的加载 2.6内核模块使用.ko的文件后缀(代替.o后缀)。 使用insmod ./hello-1.ko命令加载该模块。 /proc/modules记录被加载的内核模块。 使用lsmod命令查看
10、已经加载的模块 使用命令 rmmod hello-1 卸载模块 tail /var/log/messages 编写hello模块,包含初始化init_module和卸载函数cleanup_module 编写makefile文件 Obj-m += hello-1.o 编译hello内核模块 make -C /lib/modules/uname -r/build M=$PWD modules Uname r 给出当前系统内核的版本,使用短撇号,将其输出结果作为参数的一部分。而build是符号链接,指向对应内核的源代码目录。 加载hello内核模块: insmod hello-1.ko 查看加载信息
11、: tail /var/log/message 卸载hello内核模块 rmmod hello-1 使用modprobe命令 修改/lib/module /uname -r/modules.dep文件,添加hello-1.ko内核模块路径和依赖关系 加载hello内核模块: Modprobe hello-1 卸载hello内核模块 Modprobe r hello-1 n 修改hello内核模块的makefile n 添加all目标 n 添加clean目标 obj-m += hello-1.o KERN_VER = $(shell uname -r) KERN_DIR = /lib/modul
12、es/$(KERN_VER)/build all: $(MAKE) -C $(KERN_DIR) M=$(PWD) modules clean: rm -rf *.o rm -rf *.mod.* rm -rf *.ko rm rf .tmp_version n 直接通过make,编译内核模块 n 多个文件构成的内核模块 n Makefile会帮我们完成编译和连接的工作。 n 例如 内核模块分两个文件 start.c stop.c,则Makefile这样写: obj-m += test.o test-objs := start.o stop.o 跟单个文件模块的编译方式一样,内核编译系统会将所
13、有的目标文件连接为一个文件。 n 内核模块的Makefile模块 mymodule-objs = file1.o file2.o obj-m += mymodule.o PWD = $(shell pwd) KDIR = 内核源代码路径 all: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions lsmod 列出已经挂载的内核模块 lsmod 是列出目前系统中已加载的模块的名称及大小等 效果跟通过less /proc/modules查看模块一样。 modinfo 查看模
14、块信息 modinfo 可以查看模块的信息,通过查看模块信息来判定这个模块的用途。 modinfo 模块名 modprobe 挂载新模块以及新模块相依赖的模块 modprobe 模块名,在挂载该内核模块的同时,这个模块所依赖的模块也被同时挂载。 modprobe还有其他用法,问他的“man” 。例如:modprobe -l 是列出内核中所有的模块,包括已挂载和未挂载的,读取的模块列表就位于 /lib/modules/uname -r 目录中。 rmmod 移除已挂载模块 用法:rmmod 模块名 等同于:modprobe -r 模块名 insmod 挂载模块 insmod 需要给出模块所在目录
15、的绝对路径,以及要带有模块文件名后缀 insmod /lib/modules/2.6.18/kernel/fs/vfat/vfat.ko 功能上没有modprobe 强。 depmod 创建模块依赖关系的列表 目前的的Linux 发行版所用的内核是2.6x版本,是自动解决依赖关系。 depmod -a为所有列在/etc/modprobe.conf 或/etc/modules.conf 中的所有模块创建依赖关系,并且写入到modules.dep文件 depmod e 列出已挂载但不可用的模块 为2410开发板配置编译Linux内核 内核版本:linux-2.6.24 交叉工具链:cross-3.
16、4.4.tar.gz 选择相应的配置时,有三种选择,它们分别代表的含义如下: Y-将该功能编译进内核 N-不将该功能编译进内核 M-将该功能编译成模块,可以在需要时动态插入到内核中 make xconfig,使用鼠标就可以选择对应的选项。 make menuconfig,则需要使用空格键进行选取。 如果有不明白的地方,按 shift+?的组合键来查看说明 主要配置选项 1.Code maturity level options - 应该选择 * Prompt for development and/or incomplete code/drivers 这将会在设置界面中显示还在开发或者还没有完
17、成的代码与驱动. 因为有许多设备可能必需选择这个选项才能进行配置,实际上它是安全的。 Enable loadable module support 打开可加载模块支持 2 General setup - 大部分保持默认 * Support for paging of anonymous memory (swap) 应该选择这个选项将使你的内核支持虚拟内存。 * System V IPC 应该选择 为进程提供通信机制。有些程序只有在选Y的情况下才能运行,这里一定要选。 * POSIX Message Queues POSIX的消息队列,它同样是一种IPC,应该选择 * Support for h
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 内核 模块 设计
链接地址:https://www.31ppt.com/p-3436191.html