linux驱动程序编写基础

上传人:206****923 文档编号:56866049 上传时间:2018-10-16 格式:PPT 页数:45 大小:438.50KB
返回 下载 相关 举报
linux驱动程序编写基础_第1页
第1页 / 共45页
linux驱动程序编写基础_第2页
第2页 / 共45页
linux驱动程序编写基础_第3页
第3页 / 共45页
linux驱动程序编写基础_第4页
第4页 / 共45页
linux驱动程序编写基础_第5页
第5页 / 共45页
点击查看更多>>
资源描述

《linux驱动程序编写基础》由会员分享,可在线阅读,更多相关《linux驱动程序编写基础(45页珍藏版)》请在金锄头文库上搜索。

1、Linux操作系统分析与实践 第七讲: Linux驱动程序编写基础,Linux操作系统分析与实践课程建设小组 北京大学 二零零八年春季*致谢:感谢Intel对本课程项目的资助,本讲主要内容,Linux内核模块 中断和中断处理 下半部,Linux内核模块,Linux操作系统的内核是单一体系结构(monolithic kernel) 有了模块机制后,提高Linux操作系统的可扩充性,内核编程不再是一个恶梦 什么是模块呢? 模块的全称是“动态可加载内核模块”(Loadable Kernel Module,LKM) 模块在内核空间运行 模块实际上是一种目标对象文件 没有链接,不能独立运行,但是其代码可

2、以在运行时链接到系统中作为内核的一部分运行或从内核中取下,从而可以动态扩充内核的功能 这种目标代码通常由一组函数和数据结构组成,Linux内核模块的优点与缺点,优点 使得内核更加紧凑和灵活 修改内核时,不必全部重新编译整个内核。系统如果需要使用新模块,只要编译相应的模块,然后使用insmod将模块装载即可 模块的目标代码一旦被链接到内核,它的作用域和静态链接的内核目标代码完全等价 缺点 由于内核所占用的内存是不会被换出的,所以链接进内核的模块会给整个系统带来一定的性能和内存利用方面的损失; 装入内核的模块就成为内核的一部分,可以修改内核中的其他部分,因此,模块的使用不当会导致系统崩溃; 为了让

3、内核模块能访问所有内核资源,内核必须维护符号表,并在装入和卸载模块时修改符号表; 模块会要求利用其它模块的功能,所以,内核要维护模块之间的依赖性.,Linux内核模块与应用程序的区别,C语言程序 Linux内核模块运行 用户空间 内核空间 入口 main() module_init()指定; 出口 无 module_exit()指定; 编译 gcc c Makefile 连接 ld insmod 运行 直接运行 insmod 调试 gdb kdbug, kdb, kgdb等,模块相关命令,insmod module parameters Load the module 注意,只有超级用户才能使

4、用这个命令 Rmmod Unload the module lsmod List all modules loaded into the kernel 这个命令和cat /proc/modules等价 modprobe -r Load the module specified and modules it depends,模块依赖,一个模块A引用另一个模块B所导出的符号,我们就说模块B被模块A引用。 如果要装载模块A,必须先要装载模块B。否则,模块B所导出的那些符号的引用就不可能被链接到模块A中。这种模块间的相互关系就叫做模块依赖。,最简单的内核模块例子,#include #include #

5、include static int _init hello_init(void) printk(KERN_INFO “Hello worldn“);return 0; static void _exit hello_exit(void) printk(KERN_INFO “Goodbye worldn“); module_init(hello_init); module_exit(hello_exit);,static int _init hello_init(void) static void _exit hello_exit(void) Static声明,因为这种函数在特定文件之外没有其

6、它意义 _init标记, 该函数只在初始化期间使用。模块装载后,将该函数占用的内存空间释放 _exit标记 该代码仅用于模块卸载。 Init/exit 宏:module_init/module_exit 声明模块初始化及清除函数所在的位置 装载和卸载模块时,内核可以自动找到相应的函数module_init(hello_init);module_exit(hello_exit);,编译内核模块,Makefile文件 obj-m := hello.o all: make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules c

7、lean: make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean Module includes more files obj-m:=hello.o hello-objs := a.o b.o,装载和卸载模块,相关命令 lsmod insmod hello.ko rmmod hello.ko,模块参数传递,有些模块需要传递一些参数参数在模块加载时传递#insmod hello.ko test=2参数需要使用module_param宏来声明module_param的参数:变量名称,类型以及访问许可掩码支持的参数类型 B

8、yte, short, ushort, int, uint, long, ulong, bool, charp Array (module_param_array(name, type, nump, perm),#include #include #include #include static int test; module_param(test, int, 0644);static int _init hello_init(void) printk(KERN_INFO “Hello world test=%d n” , test);return 0; static void _exit

9、hello_exit(void) printk(KERN_INFO “Goodbye worldn“); MODULE_LICENSE(“GPL“); MODULE_DESCRIPTION(“Test“); MODULE_AUTHOR(“xxx“); module_init(hello_init); module_exit(hello_exit);,导出符号表,如果一个模块需要向其他模块导出符号(方法或全局变量),需要使用:EXPORT_SYMBOL(name);EXPORT_SYMBOL_GPL(name);*注意:符号必须在模块文件的全局部分导出,不能在函数部分导出。更多信息可参考 文件

10、Modules仅可以使用由Kernel或者其他Modules导出的符号不能使用Libc /proc/kallsyms 可以显示所有导出的符号,内核模块操作/proc文件,/proc文件系统,这是内核模块和系统交互的两种主要方式之一。 /proc文件系统也是Linux操作系统的特色之一。 /proc文件系统不是普通意义上的文件系统,它是一个伪文件系统。 通过/proc,可以用标准Unix系统调用(比如open()、read()、write()、 ioctl()等等)访问进程地址空间 可以用cat、more等命令查看/proc文件中的信息。 用户和应用程序可以通过/proc得到系统的信息,并可以改

11、变内核的某些参数。 当调试程序或者试图获取指定进程状态的时候,/proc文件系统将是你强有力的支持者。通过它可以创建更强大的工具,获取更多信息。,/proc相关函数,create_proc_entry() 创建一个文件 proc_symlink() 创建符号链接 proc_mknod() 创建设备文件 proc_mkdir() 创建目录 remove_proc_entry() 删除文件或目录,Linux2.6内核中有关模块部分的改变,模块引用计数器 Linux2.4中在linux/module.h中定义了三个宏来维护实用计数: _MOD_INC_USE_COUNT 当前模块计数加一 _MOD_

12、DEC_USE_COUNT 当前模块计数减一 _MOD_IN_USE 计数非0时返回真 在Linux2.6中,模块引用计数器由系统自动维护,所以程序中有关这些宏都可以注释掉。 关于符号导出列表(list of exported symbols) Linux2.4中会用EXPORT_NO_SYMBOLS宏,来表示不想导出任何变量或函数。在Linux2.6中这个宏也已经消失。系统默认为不导出任何变量或函数。,模块程序编译方法的改变 Linux2.4中命令为:gcc Wall DMODULE D_KERNEL_ -DLINUX c 源文件名.c 其中: _KERNEL_: 即告诉头文件这些代码将在内

13、核模式下运行 MODULE: 即告诉头文件要给出适当的内核模块的定义 LINUX: 并非必要 -Wall: 显示所有warning信息。Linux2.6中必须写makefile。通过make命令编译程序。 Linux2.6中makefile的写法:(以helloworld为例) /Makefile obj-m += hello.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

14、 * 注意:all下一行需要有一个“Tab”键,不要写成空格或略去,不然系统无法识别,报错:nothing to be done for “all”。,用以加载的目标文件类型已经改变 Linux2.4中用以加载为模块的目标文件扩展名为.o Linux2.6中中用以加载为模块的目标文件扩展名为.ko在Linux2.4中,函数init_module()和函数cleanup_module()是必不可少的;而在Linux2.6 中,同样功能的函数并非一定要起这两个函数名。,Lab 模块编程,Write Two Module: Module1: Hello World Module. Load/unlo

15、ad the module can output some info. Module2: Module accepts a parameter. Load the module, output the parameters value. Modify Module1 and Module2, let Module1 exports symbols, Module2 use the symbols .*注:详见实验指导,二、中断和中断处理程序,中断处理的基本过程 When receiving an interrupt, CPU program counter jumps to a predefined address (interrupt vectors) The state of interrupted program is saved The corresponding service routine is executed The interrupting component is served, and interrupt signal is removed The state of interrupted program is restored Resume the interrupted program at the interrupted address,

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号