5、Linux内核模块开发

Linux的模块驱动

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

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

3.接着是makfile文件:

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

4.make的执行过程:

从上面的执行的过程,我们可以看到makefile的执行的过程。

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

Hello.c:

Function.c:

Makefile修改为:

最后编译的结果如下图:

内核模块的安装和卸载:

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。

时间: 2024-10-20 12:55:00

5、Linux内核模块开发的相关文章

Linux内核模块开发基础【转】

本文转载自:http://blog.csdn.net/coding__madman/article/details/51298180 1. 什么是内核模块 内核模块具有以下两个特点:1. 模块本身并不被编译进内核文件(zImage或bzImage),可以根据需求,在内核运行期间动态的安装或卸载. 2. 为什么需要内核模块 原因:Linux内核的整体结构非常庞大,其包含的组件也非常多,如何使用这些组件呢,方法1:把所有的组件都编译键内核,即:zImage或bzImage,但这样会导致一个问题:占用

linux内核模块开发基础

1. 什么是内核模块 内核模块具有以下两个特点:1. 模块本身并不被编译进内核文件(zImage或bzImage),可以根据需求,在内核运行期间动态的安装或卸载. 2. 为什么需要内核模块 原因:Linux内核的整体结构非常庞大,其包含的组件也非常多,如何使用这些组件呢,方法1:把所有的组件都编译键内核,即:zImage或bzImage,但这样会导致一个问题:占用内存过多.然后内核模块就诞生了,可以不用被编译进内核但是可以动态的添加到正在运行的内核中! 3. 如何使用内核模块 1> 安装模块 i

linux内核模块开发

一,内核模块功能: 让内核文件(zImage或bzImage)本身并不包含某组件,而是在该 组件需要被使用的时候,动态地添加到正在运行的内核中 二,内核模块安装和卸载加载:insmod (insmod hello.ko)卸载:rmmod (rmmod hello)查看:lsmod加载:modprobe (modprobe hello)modprobe如同insmod,也是加载一个模块到内核.它的不同之处在于它会根据文件/lib/modules/<$version>/modules.dep来查看

linux内核模块开发之内核兼容

因为linux内核变化非常快,每个小版本之间数据结构.接口都有可能发生变化,因此为我们写内核模块的兼容性带来了一些问题,经常在某版本上能正常编译的模块,换另一个模块就编译失败了,这时候我们就需要做内核版本兼容了,解决方法如下: 在内核时面有一个linux/version.h头文件,里面有两个宏LINUX_VERSION_CODE和KERNEL_VERSION,可利用这两个宏来协助完成兼容处理,例子代码如下: static struct nf_hook_ops mrs_ops_forward =

【整理】--Linux简单内核模块开发

1.linux 内核模块不被编译到内核文件(zImage,bzImage), 而是在运行期间动态的安装和卸载 2.内核模块包括一下几部分:主体部分设计,编译内核模块,安装卸载NHMK,可选项使用(模块申明,MK参数,符号输出) 3.简单例子: hello.c: #include<linux/init.h>#include<linux/module.h>#include<linux/kernel.h> MODULE_LICENSE("Dual BSD/GPL&q

Linux系统开发7 进程关系,守护进程

[本文谢绝转载原文来自http://990487026.blog.51cto.com] <大纲> Linux系统开发7  进程关系守护进程 终端 网络终端 Linux PCB结构体信息 进程组 修改子进程.父进程的组ID 会话组 设置一个会话脱离控制终端 生成一个新的会话 守护进程 守护进程模板 获取当前系统时间  终端 在UNIX系统中用户通过终端登录系统后得到一个Shell进程这个终端成为Shell进 程的控制终端Controlling Terminal在讲进程时讲过控制终端是保存在PCB

与一线Linux嵌入式开发project师的对话

转:与一线Linux嵌入式开发project师的对话 陈project师一直做Linux的嵌入式开发.作为在开发一线的project师.他对非常多问题的看法可能更切合实际需求,于是,通过邮件.就嵌入式开发方面的问题,请他谈了一下自己的看法: 问:关于嵌入式开发.我们准备给同学们解说一些入门知识.从你一线开发经验来说,给我们一些建议: 陈工回答: 对于嵌入式Linux入门,假设有一定基础,可以从驱动開始:假设没有基础.我个人建议还是从应用程序開始.由于从应用程序開始是最easy的,也是 最直观的.

Linux内核模块编写详解

内核编程常常看起来像是黑魔法,而在亚瑟 C 克拉克的眼中,它八成就是了.Linux内核和它的用户空间是大不相同的:抛开漫不经心,你必须小心翼翼,因为你编程中的一个bug就会影响到整个系统,本文给大家介绍linux内核模块编写,需要的朋友可以参考下 内核编程常常看起来像是黑魔法,而在亚瑟 C 克拉克的眼中,它八成就是了.Linux内核和它的用户空间是大不相同的:抛开漫不经心,你必须小心翼翼,因为你编程中的一个bug就会影响到整个系统.浮点运算做起来可不容易,堆栈固定而狭小,而你写的代码总是异步的,

Linux内核模块编程与内核模块LICENSE -《详解(第3版)》预读

Linux内核模块简介 Linux内核的整体结构已经非常庞大,而其包含的组件也非常多.我们怎样把需要的部分都包含在内核中呢?一种方法是把所有需要的功能都编译到Linux内核.这会导致两个问题,一是生成的内核会很大,二是如果我们要在现有的内核中新增或删除功能,将不得不重新编译内核. 有没有一种机制使得编译出的内核本身并不需要包含所有功能,而在这些功能需要被使用的时候,其对应的代码被动态地加载到内核中呢?Linux提供了这样的一种机制,这种机制被称为模块(Module).模块具有这样的特点. 模块本