您的位置:首页 > 运维架构 > Linux

linux内核模块范例代码及Makefile写法步骤

2017-09-14 11:34 169 查看

一 内核模块介绍

在介绍一个简单的内核hello world模块前,我们需要了解一下在嵌入式系统中内核模块到底是一个什么东东。linux内核是模块化组成的,它允许内核在运行时动态地向其中插入或从中删除代码。这些代码(包括相关的子线程、数据、函数入口和函数出口)被一并组合在一个单独的二进制镜像中,即所谓的可装载内核模块中,或简称为模块。这段是度娘的解释,简单来说,内核模块就是不被编译进内核的文件,在内核运行期间可以动态的安装或者卸载,动态是它的优点,只要我想要就要,不要就卸载,就这么简单,这样保证了内核镜像文件的身材足够瘦小,方便灵活。

二 代码分析

下面是一段入门模块的代码。

#include <linux/init.h>    //init 和 exit 相关的宏
#include <linux/module.h>  //所有模块都需要的头文件
MODULE_LICENSE("GPL"); //加上声明宏,GPL表示一种协议(声明宏为了保证代码规范一般加上,不加编译的时候会提示有问题)
static int hello_init()
{
printk(KERN_WARNING"Hello world!\n");
return 0;
}

static void hello_exit()
{
printk(KERN_WARNING"hello exit!\n");
}

module_init(hello_init);
module_exit(hello_exit);


我们发现这段程序好像少了点什么,是不是少了main函数。而我们知道main函数在c语言中的作用是当做入口函数,没有这个入口就进不了主程序,这里虽然没有main函数,但是hello_init可以替代main当做入口函数,hello_exit当做出口函数。一个在模块加载到内核时被调用( hello_init )以及一个在模块被去除时被调用( hello_exit )。moudle_init 和 module_exit 是比较特别的内核宏来指出这两个函数的角色,在写内核代码的时候,moudle_init 和module_exit已成为固定的格式了。

printk 函数在 Linux 内核中定义并且对模块可用(printk一般用在内核当中)。

三 Makefile步骤解释

obj-m := helloworld.o
KDIR := /home/S5-driver/lesson7/linux-ok6410
all:
make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm
clean:
rm -f *.o *.ko *.order *.symvers


内核模块的格式比较固定,

1 obj 这个变量指明最终产生模块的名字,如果内核模块文件只有一个,则一般取与源文件名字一样的,这里是helloworld,就直接命名为helloworld.o。

扩展一点: 如果你有一个模块名为 module.ko, 是来自 2 个源文件( 姑且称之为, file1.c 和 file2.c ), 正确的书写应当是:

obj-m := module.o

module-objs := file1.o file2.o

2 定义一个Makefile的变量KDIR(这个变量可以随便命名)。这个变量被定义成内核模块的路径地址,在我的pc上是在/home/S5-driver/lesson7/linux-ok6410这个路径中。

3 目标:make -C 表示进入后面的路径中去执行modules这个命令,而modules命令是在内核代码中执行的。M表示内核模块代码的路径,PWD表示当前代码路径,后面指明交叉编译工具链为CROSS_COMPILE=arm-linux- ARCH=arm

4 清除工作:这个根据自己的需要要清除什么文件就在后面添加*.XXX,XXX表示你要删除文件的后缀名。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux kernel