五、Linux内核模块开发

Linux的模块驱动 函数

 

  1. 接下来写个最简单的驱动程序,就像程序语言的hello world程序。
  2. 首先是:hello.c的代码:

    这是个最简单的驱动程序。就是打印hello的信息。驱动程序和咱们的程序语言结果有点不大同样。驱动模块的入口是倒数第二行的module_init()的函数。驱动模块的出口是module_exit()的函数。 spa

3.接着是makfile文件:命令行

这也是一个很简单的Makefile文件了。Obj-m后面跟的是咱们的最终目标依赖的文件hello.o。第三行的KDIR是咱们编译进的内核的路径。All是执行make获得的目标,$(KDIR)指定内核的路径,就是第三行的路径。M=$(PWD)是模块存放的路径。接着就是清除生成的文件的命令。 3d

4.make的执行过程: blog

从上面的执行的过程,咱们能够看到makefile的执行的过程。 字符串

 

 

 

若是在一个工程里,当有两个.c文件的时候的编写: it

Hello.c: io

Function.c: 编译

Makefile修改成: function

最后编译的结果以下图:

 

 

 

 

 

内核模块的安装和卸载:

insmod hello.ko

卸载内核模块:

rmmod hello(卸载的时候不用加.ko)

查看模块:

lsmod

 

执行的结果:

注意:内核模块只有当没有用户用时才能够卸载,如上图:咱们的test是没有被使用,而fuse有两个用户在使用。咱们试着卸载这两个内核模块的截图:

 

 

 

内核模块的可选的信息:模块申明、模块参数、符号信息。

模块的申明:

    MODULE_LICENSE("遵照的协议")

申明该模块遵照的许可证协议,如:"GPL"、"GPL v2"等。

    MODULE_AUTHOR("做者")

    申明模块的做者

    MODULE_DESCRIPTION("该模块的功能描述")

    MODULE_VERSION("v1.0")

申明模块的版本

 

模块申明可让读者知道该模块所遵照的协议,增长模块代码的可读性。

 

 

只是一个提示,增长可读性的做用。

 

模块参数的传递:

在咱们的应用程序中:int main(int argc,char** argv):argc表示命令行输入的参数个数,argv中保存输入端的参数。

那么咱们的内核模块中是怎么传入参数的呢?:

 

模块参数跟咱们程序语言的参数有点不大同样,除了用通常的数据类型来申明变量参数,咱们还得用module_param()这个宏来指定它是模块参数:

Module_param(name,type,perm):

Name:变量的名称

Type:变量的类型,bool,int,charp。

Perm:访问权限。S_IRUGO:读权限。S_IWUSR:写权限。

例如:

Int a=33;

Char *st;

Module_param(a,int ,S_IRUGO);

Module_param(st,charp,S_IRUGO);

 

下面是执行的实例:

咱们定义了一个a=99;而后在14行打印出来。运行的结果:

上面是执行的过程,咱们也能够在执行的时候给它加参数:

字符串也是同样:

运行的结果:

 

 

最后是符号导出:

符号导出的实例:

修改Makefile:

 

修改function.c为:

 

执行的过程:

 

同时产生了两个.ko模块。

当咱们去安装hello.ko的时候,出现了这个错误:未定义的符号:

这是由于咱们程序中的extern int function();如今的系统中不存在这个函数。那是否是得先insmod function.ko呢!?

虽然系统已经出现了function函数,但是系统仍是找不到。能够看出错误依然存在。

 

这就是模块导出的问题:当咱们要去使用一个模块里面的变量,函数的时候,必须使用符号导出。也就是把变量和函数输出到咱们的系统当中,使整个系统均可以使用。

修改function.c为:

用EXPORT_SYMBOL()来申明,个人function是能够被系统的其余模块使用的。不过,咱们应该先编译function.ko,在编译hello.ko。结果:

这就是符号输出的使用。

总结与应用程序的区别:

内核的打印:

Printf和printk都是打印信息的。可是printk还有级别打印:

Hello.c:

 

输出结果:

结果只有KERN_EMERG级别的才在屏幕打印出来。这样的打印级别,咱们能够控制在那些地方能够打印什么。固然,咱们也能够用输入来代替级别。例如上面的"<0>",就是KERN_EMER。

 

相关文章
相关标签/搜索