实验五动态加载驱动模块一、实验目的:通过本实验掌握驱动程序动态加载的原理以及动态加载的步骤,另外掌握ARM开发板烧写的内容及步骤。二、实验设备:1、安装vmware8.0及unbuntu10.10的计算机2、TQ2440开发板3、串口线4、USB线三、实验原理:1、驱动动态加载原理:Linux则是单块结构的操作系统。微内核结构可方便地在系统中添加新的组件,而单块结构却不容易做到这一点。为此,Linux系统使用可动态加载和卸载的内核模块(LoadableKernelModules,LKMs),可方便地在内核中添加新的组件或卸载不再需要的内核组件。Linux使用insmod来显式加载内核模块,使用rmmod来卸载模块。同时内核自身也可以请求内核后台进程kerneld来加载与卸载模块。Linux模块大多数是设备驱动程序以及伪设备驱动程序模块,如网络设备和文件系统等。动态可加载代码的优点是可以让内核保持很小的尺寸并非常灵活。模块机制可以无需重构内核并频繁重新启动来尝试运行新内核代码。用户可以根据自己系统的需要构筑自己的私有内核。Linux源码的公开更是为改造其内核、重建有特殊要求的操作系统提供了可能。模块必须能够找到其需要使用的内核资源。例如模块需要分配内存时,要调用内核的内存分配例程kmalloc()。但在构造模块时并不知道kmalloc()在内存中何处,这样内核必须在使用这些模块前修改模块中对kmalloc()的引用地址。内核在其内核符号表中维护着一个内核资源链表这样当加载模块时它能够解析出模块中对内核资源的引用。Linux还允许存在模块堆栈,它在模块之间相互调用时使用。例如,因为VFAT(VirtuaIFileAllocationTable)文件系统是从FAT(FileAllocationTable)文件系统中扩展而来,VFAT文件系统模块可能需要FAT文件系统模块的服务。某个模块对其他模块的服务或资源的需求类似于模块对内核本身资源或服务的请求。不过此时所请求的服务是来自另外一个事先已加载的模块。当加载模块时,内核就把新近加载模块输出的所有资源和符号添加到内核符号表(Kernel-Symbol-Table)中。在/proc/ksyms.里面的每一个表项代表着一个公共的内核符号,这就是内核符号表。这些内核符号是可以被LKM引用的。LKM中所存取的每一个符号(像函数名)也会被列在这个文件里面。在该文件中可以看到LKM到底可以调用那些函数。当试图卸载某个模块时,内核需要知道此模块是否已经没有被使用,同时它需要有种方法来通知此将卸载模块。模块必须能够在从内核种删除之前释放其分配的所有系统资源,如内核内存或中断。当模块被卸载时,内核将从内核符号表中删除所有与之对应的符号。有两种方法可用来加载模块:(1)利用insmod命令手工将模块插入内核;(2)由内核在必要时加载模块,称为“需求加载”。2、动态加载的步骤原理Linux的模块可以用C语言编写,用gcc编译成目标文件(不进行链接,作为*.o文件存在),为此需要在gcc命令行里加上-c的参数。在编译时,还应该在gcc的命令行里加上这样的参数:-D_KERNEL_-DMODULE。由于在不链接时,gcc只允许一个输入文件,因此一个模块的所有部分都必须在一个文件里实现。编译好的模块*.o放/lib/modules/xxxx/misc下(xxxx表示核心版本,如在核心版本为2.0.30时应该为/lib/modules/2.0.30/misc),然后用depmod-a使此模块成为可加载模块。模块用insmod命令加载,用rmmod命令来卸载,并可以用lsmod命令来查看所有已加载的模块的状态。利用insmod命令可手工装入内核模块;利用lsmod可查看当前装入的内核模块以及需求加载模块的使用计数及标志信息;利用rmmod则可以卸载指定的模块。编写模块程序的时候,必须提供两个函数,一个是intinit_module(void),供insmod在加载此模块的时候自动调用,负责进行设备驱动程序的初始化工作。init_module返回0以表示初始化成功,返回负数表示失败。另一个函数是voidcleanup_module(void),在模块被卸载时调用,负责进行设备驱动程序的清除工作。在成功的向系统注册了设备驱动程序后(调用register_chrdev成功后),就可以用mknod命令来把设备映射为一个特别文件,其它程序使用这个设备的时候,只要对此特别文件进行操作就行了。四、实验步骤:(一)、驱动模块动态加载1.找到驱动程序EmbedSky_led.c的位置,此处源代码放置在/LED/drv2.编译驱动程序:将EmbedSky_led.c利用编译器编译成为EmbedSky_led.ko,或者根据已经编写好的MAKEFILE,运行MAKE,将驱动源程序编译成模块文件。附:MAKEFILE内容:ifneq($(KERNELRELEASE),)obj-m:=EmbedSky_led.oelseKDIR:=/opt/EmbedSky/linux-2.6.30.4PWD:=$(shellpwd)default:$(MAKE)-C$(KDIR)M=$(PWD)modulesclean:rm-rf*.o*~core.depend.*.cmd*.ko*.mod.c.tmp_versionsendif3.传送驱动程序至开发板:利用串口方式,或者网络方式打开超级终端打开传送,将EmbedSky_led.ko,传送至开发板4.加载驱动模块:利用命令insmod加载驱动模块命令:Insmod/路径/EmbedSky_led.ko若是加载成功,会显示dzledinitialed5.编译并运行测试程序打开测试程序源代码目录:/Led/app/leds编译源代码(leds_test.c):make将编译好的执行文件传送至开发板运行执行文件