驱动开发-Linux内核模块Hello world_第1页
驱动开发-Linux内核模块Hello world_第2页
驱动开发-Linux内核模块Hello world_第3页
驱动开发-Linux内核模块Hello world_第4页
驱动开发-Linux内核模块Hello world_第5页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Linux内核模块HelloWorld一、确定任务了解内核模块的概念。掌握基本的驱动程序设计。二、 学习内容 1、 内核模块概述Linux内核是整体式结构,各个子系统联系紧密,作为一个大程序在内核空间运行。太多的设备驱动程序和内核功能集成在内核中,内核过于庞大。如何解决?Linux内核引入内核模块制。通过动态加载内核模块,使得在运行过程中扩展内核的功能。不需要的时候。卸载该内核模块。什么是内核模块?内核模块式一种没有经过链接,不能独立运行的目标文件,是在内核空间中运行的程序。经过链接装载到内核里面成为内核的一部分,可以访问内核的公用符号(函数和变量)内核模块可以让操作系统内核在需要是载入和执行

2、,在不需要时由操作系统卸载。它们扩展了操作系统讷河的功能却不需要重新启动系统。如果内有内核模块,我们不得不一次又一次重新编译生成单内核操作系统的内核镜像来加入新的功能。还意味着一个臃肿的内核。内核模块是如何被调入内核工作的? 当操作系统内核需要的扩展功能不存在时,内核模块管理守护进程 kmod 执行 modprobe 去加载内核模块。modprobe 遍历文件/lib/modules/version/modules.dep来判断是否有其它内核模块需要在该模块加载前被加载。最后 modprobe 调用 insmod 先加载被依赖的模块,然后加载该被内核要求的模块。2、模块机制的优缺点模块机制的优

3、点:减小内核映像尺寸,增加系统灵活性;节省开发时间;修改内核,不必重新编译整个内核。 模块的目标代码一旦被链入内核,作用和静态链接的内核目标代码完全等价。模块机制的缺点:对系统性能有一定损失; 使用不当时会导致系统崩溃。3、内核模块函数入口与出口函数:初始化函数 module_init(),在模块加载到内核时被调用。module_init()要么向内核注册 它可以处理的事物,要么用自己的代码替代某个内核函数。卸载函数 module_exit()或者cleanup_module(),在内核模块被卸载时被调用,干一些收尾清理的工作, 撤消任何初始化函数module_init()做的事,保证内核模块

4、可以被安全的卸载。(注意:任一个内核模块需要包含 linux/module.h)(1)printk( )函数:printk 函数在 Linux 内核中定义并且对模块可用,为内核提供日志功能, 记录内核信息或用来给出警告。与标准 C 库函数 printf 的行为相似。每个 printk()声明都会带一个优先级。内核总共定义了八个优先级的宏, 在 linux/kernel.h 中定义。若你不指明优先级,DEFAULT_MESSAGE_LOGLEVEL 这个默认 优先级将被采用。信息添加到文件 /var/log/messages,可直接查看,或者用命令 dmesg 查看。在 Xwindows 下的终

5、端 insmod 一个模块,日志信息只会记录在日志文件中,而不在终端打印。(2)内核模块编译顺利编译并且加载第一个“hello world”模块有时就会比较困难。强烈建议使用标准内核源代码包,编译新内核并用新内核启动系统。Linux 的发行版本经常给内核打一些非标准的补丁,这种情况会导致一些问题的发生。保 证 系 统 具 备 正 确 的 编 译 器 、 模 块 工 具 、 以 及 其 他 必 要 工 具 。 内 核 目 录Documentation/Changes 列出了需要的工具版本。用错误的工具版本建立一个内核(包括模块),可能导致一些奇怪复杂的问题。内核模块编译:为 2.6 版本内核构造

6、模块,首先需要有配置并构建好的 2.6 内核源代码树。而且最好运行和模块对应的内核。 2.6内核的模块要和内核源代码树中的目标文件连接。2.6 内核的构建系统 kbuild,使得内核源码外的内核模块编译跟内核编译统一起来,无须手动给定这些参数。Hello-1.c 的 Makefile 文件:obj-m += hello-1.o表明有一个模块要从目标文件 hello-1.o 建立,kbuild 从该目标文件建立内核模块hello-1.ko。执行以下命令编译模块:make -C /usr/src/linux-uname -r M=$PWD modules改变目录到用 -C 选项提供的内核源码目录,

7、在那里找到内核的顶层 makefile。M= 选 项使 makefile 在试图建立模块目标前, 回到模块源码目录。2.6 内核引入新的内核模块命名规范:内核模块使用.ko 的文件后缀(代替 以往的.o 后缀),从而内核模块区别于普通的目标文件。多个文件构成的内核模块:*Makefile 会帮我们完成编译和连接的工作。例如 内核模块分两个文件 start.c stop.c,则 ;Makefile 这样写:obj-m += startstop.ostartstop-objs := start.o stop.o跟单个文件模块的编译方式一样,内核编译系统会将所有的目标文件连接为一个文件。 内核模块和

8、用户程序的比较内核模块是如何开始和结束的:*用户程序通常从函数 main()开始,执行一系列的指令并且 当指令执行完成后结束程 序。从头到尾执行任务。*内核模块从函数 module_init() 指定的函数调用开始。这就是内核模 块的入口函数。初始化函数的任务注册自己,为以后内核调用模块函数做准备。*模块的退出函数则在模块别卸载之前调用,撤销“初始化函数”注册的扩展功能。 *模块可调用的函数*应用程序可以调用它没有定义的函数(函数库中的函数)。因为在连接阶段与合适的函 数库连接,解决外部引用。*内核模块是连接到内核, 它能够调用的函数和变量是内核公开的函数和变量,没有库来连接。可以在内核模块中

9、使用的函数只能来自内核本身。(3)管理内核模块的命令lsmod 列出已经挂载的内核模块*lsmod 是列出目前系统中已加载的模块的名称及大小等*效果跟通过 less /proc/modules 查看模块一样。*modinfo 查看模块信息* modinfo 可以查看模块的信息,通过查看模块信息来判定这个模块的用途。* modinfo 模块名 管理内核模块的命令*modprobe 挂载新模块以及新模块相依赖的模块*modprobe 模块名,在挂载该内核模块的同时,这个模块所依赖的模块也被同时挂载。*modprobe 还有其他用法,具体用法查看man modprobe 。例如:modprobe -

10、l 是列出内核中所有的模 块,包括已挂载和未挂载的,读取的模块列表就位于 /lib/modules/uname -r 目录中。*rmmod 移除已挂载模块*用法:rmmod 模块名(不带后缀)*等同于:modprobe -r 模块名*insmod 挂载模块*insmod 需要给出模块所在目录的绝对路径,以及要带有模块文件名后缀(.o 或.ko)*insmod *.ko*功能上没有 modprobe 强。 *depmod 创建模块依赖关系的列表*目前的的 Linux 发行版所用的内核是 2.6x 版本,是自动解决依赖关系。*depmod -a 为所有列在/etc/modprobe.conf 或/

11、etc/modules.conf 中的所有模块创建依赖 关系,并且写入到 modules.dep 文件*depmod e 列出已挂载但不可用的模块。(4)注意事项*使用 insmod ./hello-1.ko 命令加载该模块。*/proc/modules 记录被加载的内核模块。*使用命令 rmmod hello-1 卸载模块*改变 module_init()返回值非零,重新编译再加载,观察结果发生了什么变化?*非 0 返回值表示初始化内核模块失败,模块不能加载。*从内核 Linux 2.4 之后,可以为模块的“初始化”和“卸载”函数起任意的名字。不再必须 使用 init_module()和 c

12、leanup_module()的名字。*通过宏 module_init()和 module_exit()实现。这些宏在 linux/init.h 中定义。module_init(hello_2_init); module_exit(hello_2_exit);*函数必须在宏的使用前定义,否则编译会报错。(5)关于 init 和exit 宏*如果该模块被编译进内核,而不是动态加载,则宏 init 的使用会在初始化完成后丢 弃该函数并收回所占内存。*如果该模块被编译进内核,宏 exit 将忽略“清理收尾”的函数。*这些宏在头文件 linux/init.h 定义,用来释放内核占用的内存。例如启动时看

13、到的信息“Freeingunusedkernelmemory:236kfreed”,正是内核释放这些函数所占用空间时的打印信息。三、代码设计 一、 编写源程序代码#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>static int _init hello_init(void) printk("module initn"); printk("Hello worldn"); return 0;static void _exit

14、 hello_exit(void) printk("module exitn");module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");二、 编写makefile文件ifneq ($(KERNELRELEASE),) obj-m :=hello.oelsemodule-objs :=hello.oKERNELDIR ?= /home/gec/linux_kernel#若仅编译宿主机的驱动模块则将KERNELDIR 替换成以下语句#KERNELDIR ?=/lib/modules/$(shell uname r)/build/PWD := $(shell pwd)modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modulesendifclean: $(RM) *.ko *.mod.c *.mod.o *.o *.order *.symvers *.cmd四、编译代码和运行在Ubuntu下建立目录/home/

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论