内核模块开发 初步

来源:互联网 发布:大学入伍体检 知乎 编辑:程序博客网 时间:2024/05/16 08:33

LINUX内核模块基础

什么是内核模块:
Linux内核的整体结构非常庞大,其包含的组件也非常多,如何使用这些组件呢,有一种方法是:把所有的组件都编译进内核文件,即:zImage或bzImage,但这样会导致一个问题:占用内存过多。
应当采用一种机制能让内核文件本身并不包含某组件,而是在该组件需要被使用的时候,动态地添加到正在运行的内核中。

内核模块具有如下特点:
• 模块本身并不被编译进内核文件(zImage或者bzImage)。
• 可以根据需求,在内核运行期间动态的安装或卸载。

安装与卸载内核模块:
安装 insmod
例:insmod /home/dnw_usb.ko

卸载 rmmod
例:rmmod dnw_usb

查看 lsmod
例:lsmod

内核模块设计

内核模块C程序代码举例:

//Linux内核模块的三要素:头文件、加载函数、卸载函数#include <linux/init.h>#include <linux/module.h>//加载和卸载函数都要加上static静态函数//在内核中打印不能使用 printf ,要使用 printk 函数static int hello_init(){    printk(KERN_WARNING"Hello world!\n");//没有逗号,KERN_WARNING 是优先级    return 0;   }static void hello_exit(){    printk(KERN_WARNING"hello exit!\n");    }module_init(hello_init); //加载函数,insmod命令之后自动开始执行括号内的函数module_exit(hello_exit); //卸载函数,rmmod命令之后自动开始执行括号内的函数

makefile文件编写:

obj-m := helloworld.o#helloworld.o是最终生成的内核模块的名字,上面是单个文件的写法#多个文件的写法:#obj-m := hello.o#hello-objs := file1.o file2.o file3.oKDIR := /home/ARM_Linux/system2/season4/First/part3/linux-ok6410 #开发板上运行的内核代码的路径,编译内核需要依赖于内核路径,注意斜线方向all:    make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm    # -C 表示进入后面的路径中,因此还需要加上内核模块代码的路径    # pwd 是内核模块代码的路径clean:    rm -f *.o *.ko *.order *.symvers *.bak *.mod.c

对代码进行编译,可以得到 .ko 文件,将 .ko 文件拷贝到嵌入式系统的根文件系统中。

在嵌入式系统上,用insmod命令加载模块和用rmmod命令写在模块,都可以看到程序的运行效果。

内核模块可选信息

该部分是模块中可选的信息,可有也可以没有。

模块申明:
加入下面的宏,声明相应的信息:

1、MODULE_LICENSE(“遵守的协议”);
申明该模块遵守的许可证协议,如:GPL、GPL v2等

2、MODULE_AUTHOR(“作者”);
申明模块的作者

3、MODULE_DESCRIPTION(“模块的功能描述”);
申明模块的功能

4、MODULE_VERSION(“V1.0”);
申明模块的版本

模块参数:
在应用程序中:

int main(int argc, char** argv)

argc表示命令行输入的参数个数,argv中保存输入的参数。

内核模块中可以通过命令行输入参数,例如:

insmod xx.ko 某个变量=某个值(该变量必须在程序中用宏指定)

但是,必须先通过宏module_param指定保存模块参数的变量。模块参数用于在加载模块时传递参数给模块。

module_param(name, type, perm);

name:变量的名称
type:变量类型,bool:布尔型,int:整型,charp:字符串型。
perm:是访问权限。 S_ IRUGO:读权限,S_IWUSR:写权限。

例程,传入两个参数:

int a = 3;char *st;module_param(a,int, S_IRUGO|S_IWUSR);module_param(st,charp, S_IRUGO|S_IWUSR);insmod xx.ko a=xx st=xx

符号导出:
一个模块的数据给其他模块使用必须要进行符号导出。

内核符号的导出使用宏

EXPORT_SYMBOL(符号名);EXPORT_SYMBOL_GPL(符号名);//符号名可以是变量,可以是函数名//调用该符号的文件要使用extern声明该符号//同时还要注意不同内核的安装顺序

说明:
其中EXPORT_ SYMBOL_GPL只能用于包含GPL许可证的模块。

原创粉丝点击