基于 Linux 内核驱动模块的简介
最简内核驱动原理
内核编程的最简单表现就是内核模块, 它可以作为一段可动态加载的成熟的内核级的代码使用。使用时一般不限制模块个数和类型,即插即用, 高效快捷、 性能稳定。缺点为性能和内存利用缺失, 模块间的依赖关系有着严密的逻辑结构,使用不当可能造成系统崩溃, 因为对于一般程序而言, 内核都会有安全保护机制以防其止造成内核故障。 但是在运行内核级代码的时候, 使用不当可能会出现异常而影响整个系统,造成系统锁定、内存泄漏或引入死循环等问题。 所以在编写内核代码时首先要保证代码的严谨性,其次要遵循内核库的标准, 最后在卸载内核模块时要回收内存和清理系统垃圾。
在 PC 机上通过交叉编译器编译内核模块时,会根据包含的头文件对源码进行索引, 因此必须要保证代码编译依赖源码和目标机运行内核源码版本相符。此环境中编译的模块才能(也是只能) 被运行于该版本内核系统中,否则一个微小的异常就可能引起内核锁定或模块编译异常失败。 所以编译内核模块必需有相对应的内核源码和相关的编译配置文件以及所需要编译的程序代码。以一个最简驱动模块举例, 其编译时所需的几个主要部分如图所示:
以一个最简字符驱动代码为例,其主要包含如表 2-1 所示的几项内容。
使用 make 命令编译内核驱动模块时,会根据 Makefile 文件中的 KERNELDIR 参数索引到 Linux 内核源码中去编译[5], 结合所需资源, 在当前目录下生成很多临时文件以及驱动模块文件*.ko。 *.ko 文件即所需要的内核驱动模块, 大致编译过程为如图所示。 首先调用 Makefile, 然后分为两条路径进行,一是通过添加的源码路径搜索需要的编译用的源码, 会索引源码相关目录,添加对应头文件等, 然后整合资源信息在 Makefile 同级目录下找到需要编译的.c 文件, 编译需要的.ko 文件。