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

内核模块开发 初步

2017-06-19 22:10 337 查看

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.o

KDIR := /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许可证的模块。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息