简单实例讲解linux的module模块编译步骤

原博文地址http://blog.sina.com.cn/s/blog_4ba5b45e0102v25h.html

-------------------------------------------------------------------------------------------------------------------------------------------

本文将直接了当的带你进入linux的模块编译。当然在介绍的过程当中,我也会添加一些必要的注释,以便初学者能够看懂。之所以要写这篇文章,主要是因为从书本上学的话,可能要花更长的时间才能学会整个过程,因为看书的话是一个学习过程,而我这篇文章更像是一个培训。所以实践性和总结性更强。通过本文你将会学到编译一个模块和模块makefile的基本知识。以及加载(卸载)模块,查看系统消息的一些知识;

声明:本文为初学者所写,如果你已经是一个linux模块编译高手,还请指正我文章中的错误和不足,谢谢

第一步:准备module源代码


首先我们还是要来编写一个符合linux格式的模块文件,这样我们才能开始我们的模块编译。假设我们有一个源文件mymod.c。它的源码如下:

mymod.c

 1 #include <linux/module.h>         /* 引入与模块相关的宏 */  2 #include <linux/init.h>               /* 引入module_init() module_exit()函数 */  3 #include <linux/moduleparam.h>/* 引入module_param() */  4 MODULE_AUTHOR("Yu Qiang");  5 MODULE_LICENSE("GPL");   6 static int nbr = 10;  7 8 module_param(nbr, int, S_IRUGO);   /* 加载模块时传入参数 */9
10 static int __init yuer_init(void)          /* 加载模块时自动执行 */
11 {
12     int i;
13     for(i=0; i<nbr; i++)
14     {
15         printk(KERN_ALERT "Hello, How are you. %d\n", i);
16     }
17     return 0;
18 }
19
20 static void __exit yuer_exit(void)
21 {
22     printk(KERN_ALERT"I come from yuer's module, I have been unlad.\n");
23 }
24 module_init(yuer_init);
25 module_exit(yuer_exit);  

我们的源文件就准备的差不多了,这就是一个linux下的模块的基本结构。

第8行,是导出我们的符号变量nbr,这样在你加载这个模块的时候可以动态修改这个变量的值,稍后将演示。

第10行,yuer_init()函数将在模块加载的时候运行,通过输出的结果可以看到我们的模块是否加载成功。

第二步:编写Makefile文件


首先还是来看看我们Makefile的源文件,然后我们再来解释;

Makefile

 1 obj-m := modules.o                   #要生成的模块名     2 modules-objs:= mymod.o        #生成这个模块名所需要的目标文件3 4 KDIR := /lib/modules/`uname -r`/build5 PWD := $(shell pwd)6 7 default:8     make -C $(KDIR) M=$(PWD) modules9
10 clean:
11     rm -rf *.o .* .cmd *.ko *.mod.c .tmp_versions

现在我来说明一下这个Makefile。请记住是大写的Makefile而不是小写的makefile;
obj-m :这个变量是指定你要声称哪些模块,即模块名称,模块的格式为 obj-m := <模块名>.o,一个目录下可以有多个obj-m模块文件,详见kernel源码
modules-objs :这个变量是说明声称模块modules需要的目标文件,格式要求   <模块名>-objs := <目标文件>
       切记:模块的名字不能取与目标文件相同的名字。如在这里模块名不能取成 mymod;
KDIR   :这是我们正在运行的操作系统内核编译目录,也就是编译模块需要的环境,注意,这儿如果是PC module则路径为PC内核路径,如果ARM板则路径为SDK 内核路径
M=     :指定我们源文件的位置
PWD   :这是当前工作路径$(shell  pwd)是make的一个内置函数。用来执行shell命令。
default:第一个目标为Makefile中默认执行的目标

第三步:编译模块


现在我们已经准备好了我们所需要的源文件和相应的Makefile。我们现在就可以编译了。

在终端进入源文件目录输入make
运行结果:

1 make[1]: Entering directory `/usr/src/linux-headers-2.6.24-24-generic'
2 CC [M] /home/yuqiang/桌面/mymodule/mymodules.o
3 LD [M] /home/yuqiang/桌面/mymodule/modules.o
4 Building modules, stage 2.
5 MODPOST 1 modules
6 CC      /home/yuqiang/桌面/mymodule/modules.mod.o
7 LD [M] /home/yuqiang/桌面/mymodule/modules.ko
8 make[1]: Leaving directory `/usr/src/linux-headers-2.6.24-24-generic'  

第四步:加载/卸载我们的模块


从上面的编译中我可以看到。已经有一个modules.ko生成了。这就是我们的模块了。现在我们就可以来加载了。
首先在终端输入:sudo insmod modules.ko
现在我们来看看我们的模块加载成功没有呢?
在终端输入:dmesg | tail -12   这是查看内核输出信息的意思。tail -12 显示最后12条;
显示结果如下:

 1 [17945.024417] sd 9:0:0:0: Attached scsi generic sg2 type 0  2 [18046.790019] usb 5-8: USB disconnect, address 9  3 [19934.224812] Hello, How are you. 0  4 [19934.224817] Hello, How are you. 1  5 [19934.224818] Hello, How are you. 2  6 [19934.224820] Hello, How are you. 3  7 [19934.224821] Hello, How are you. 4  8 [19934.224822] Hello, How are you. 5  9 [19934.224824] Hello, How are you. 6
10 [19934.224825] Hello, How are you. 7
11 [19934.224826] Hello, How are you. 8
12 [19934.224828] Hello, How are you. 9  

看到了吧。我们的模块的初始化函数yuer_init();已经成功运行了。说明我们的模块已经加载成功;
现在我们再来卸载模块试试看。
在终端输入:sudo rmmod modules
在终端输入:dmesg | tail -3

1 [19934.224826] Hello, How are you. 8
2 [19934.224828] Hello, How are you. 9
3 [20412.046932] I come from yuer's module, I have been unlad.  

可以从打印的信息中看到,我们的模块的退出函数已经被执行了。说明我们的模块已经被成功的卸载了。到目前位置我们就已经算是对模块的编译到编译运行算是有了一个整体上的认识了。对于以后深入的学习还是应该有点帮助的。下面我们将在看看于模块相关的一些简单的操作。

第五步:加载模块时传递参数


在终端输入:sudo insmod module_name.ko nbr=4
在终端输入:dmesg | tail -6
显示结果如下:

1 [20800.655694] Hello, How are you. 9
2 [21318.675593] I come from onefile module, I have been unlad.
3 [21334.425373] Hello, How are you. 0
4 [21334.425378] Hello, How are you. 1
5 [21334.425380] Hello, How are you. 2
6 [21334.425381] Hello, How are you. 3  

这样我们就可以看到在模块加载的时候动态设置了我们的一个变量。初始化函数中的循环只执行了4次。
可能你会问我怎么知道一个模块可以设置那些变量呢。当然,你可以先不设变量加载一次。然后可以在终端输入ls /sys/module/<modules_name>/parameters/来查看。在这里我们是这样输入的
在终端输入:ls /sys/moedle/modules/parameters/
显示结果:

1 nbr

如果我们的模块加载成功了。最后我们还可以通过modinfo来查看我们的模块信息。如下
在终端输入:sudo modinfo modules.ko
    显示结果:

1 filename:       modules.ko
2 license:        GPL
3 author:         Yu Qiang
4 srcversion:     20E9C3C4E02D130E6E92533
5 depends:
6 vermagic:       2.6.24-24-generic SMP mod_unload 586
7 parm:           nbr:int  

本文总结:


本文的相关知识都好像有一点浅尝辙止的感觉。因为本篇文章主要是通过一条线式方式来讲解了模块编写的相关过程,其实在这个过程中还有很多可以发散的地方。例如:
在写到MODULE_AUTHOR("Yu Qiang")的时候,你应该想到还有
    MODULE_DESCRIPTION(模块用途的简单描述);
    MODULE_VERSION(模块的版本字符串);
    MODULE_ALIAS(模块的别名);
    ...

在写到module_param(nbr, int, S_IRUGO);的时候,你应该想到还有
     EXPORT_SYMBOL(name); 可以导出模块的函数,这也是模块编写的最终目的
...

在用到insmod 和 modinfo的时候。你应该想到还有
    depmod     分析可加载模块的依赖性,并生成modules.dep文件和映射文件
    modprobe   Linux内核添加删除模块
...

如果要成为一名专业的linux模块开发人员,还要走很多的路,就看各位的了,祝大家学习顺利。

我并不是什么linux相关的专家,我只是一个普通的linux相关开发人员(在读),我的目的也很简单,就是想给大家介绍一个方法,希望大家在学习的时候不要走过多的弯路。由于个人能力所限难免存在错误和缺点,所以请不要介意,如有发现请提出,我立即修改。方便大家学习

Android 驱动(8)---简单实例讲解linux的module模块编译步骤相关推荐

  1. 简单实例讲解linux的module模块编译步骤

    简单实例讲解linux的module模块编译步骤 (2014-10-24 10:19:17) 标签: module linux 分类:Linux/Unix 本文将直接了当的带你进入linux的模块编译 ...

  2. linux 命令 cd -p,Linux_实例讲解Linux中cd命令切换目录的使用技巧,cd命令大家再熟悉不过了,bash sh - phpStudy...

    实例讲解Linux中cd命令切换目录的使用技巧 cd命令大家再熟悉不过了,bash shell经常会被用到的切换目录命令. 接下来我们直接通过万能的man来了解cd命令. 直接 man cd 是不行的 ...

  3. 实例讲解Linux系统中硬链接与软链接的创建

    导读 Linux链接分两种,一种被称为硬链接(Hard Link),另一种被称为符号链接(Symbolic Link).默认情况下,ln命令产生硬链接.硬链接与软链接的区别从根本上要从Inode节点说 ...

  4. 【JEECG技术博文】简单实例讲解JEECG ONLINE表单权限控制(jeecg3.6)

    简单实例讲解JEECG ONLINE表单权限控制(jeecg3.6) 原       文:http://blog.itpub.net/30066956/viewspace-1872409/ 相关博文: ...

  5. 【JEECG技术博文】JEECG 简单实例讲解权限控制

    JEECG简单实例讲解权限控制 请大家点击这里为我们投票,2015博客之星,更多分享敬请期待 博文地址:http://blog.itpub.net/30066956/viewspace-1868754 ...

  6. 安卓Android ViewModel 超简单实例

    安卓Android ViewModel 超简单实例 文章目录 安卓Android ViewModel 超简单实例 前言 使用步骤 1.引入库 2.继承ViewModel 并定义一个对象 3.到处去用 ...

  7. linux ksh 用户名,实例讲解Linux中ksh的用法

    实例讲解Linux中ksh的用法 发布时间:2008-02-18 20:46:01来源:红联作者:Modegle 熟悉Linux的朋友肯定都知道bash,它是Linux默认的命令行解释程序,熟悉Sol ...

  8. exfat linux 驱动_(实例)Linux 内核添加exfat驱动

    背景: 由于exfat是常用的文件系统格式,而Linux由于版权的问题,没有在官方中添加有关的驱动. 但是 微软也同意开源了,所以比较新的 Linux 会支持这一块. 为了支持exfat的驱动,我们需 ...

  9. HTML5-canvas标签结合简单实例讲解

    关于Canvas的简单介绍 <canvas>元素是HTML5中的新元素,该标签只是图形容器,需要使用脚本语言来绘制图形. 浏览器支持 Internet Explorer 9+, Firef ...

最新文章

  1. QQ群功能设计与心理学
  2. 人脸识别最前沿在研究什么?
  3. 管理员端API——任仲行
  4. Eclipse新建工程编译R cannot be resolved to a variable问题
  5. CentOS 7.6 MySQL 8.0 RPM包方式安装及新特性介绍
  6. boost::spirit模块利用 std::tuple 将多个属性包装成一个的测试程序
  7. 阿里巴巴400集python教程_递归的练习课程 | Python从入门到精通:高阶篇之十二-阿里云开发者社区...
  8. 如何用ChemFinder制作子表单
  9. class参数传入 python_小白学 Python 爬虫(20):Xpath 进阶
  10. python字符串格式化_Python3 字符串格式化
  11. 机器学习—XGBoost实战与调参
  12. 易考防作弊功能有哪些_浙江考试院发公告,上百名考生考研违规,你可以不努力但不能作弊...
  13. redux-saga中间件的安装和使用-(三)
  14. mysql针对特定表不做binlog_MySQL笔记--主从复制
  15. revit2016注册表删除_Revit怎么卸载,如何把revit彻底卸载删除干净重新安装的方法?【转载】...
  16. OICQ登录号码清除器实现原理 (转)
  17. 在线制作流程,数据库模型,网络架构图,你所不知道的工具使用-Freedgo Design
  18. 儿童摄影HTML实现
  19. C++ 如何判断姓名字符串符合百家姓
  20. Navicat导出数据库设计文档

热门文章

  1. python算法应用(八)——优化
  2. 数据结构之内部排序一
  3. 深入理解ARM体系架构(S3C6410)---lcd 显示图片
  4. 【数据结构】----C语言实现栈操作
  5. php的toast,jQuery 一句代码轻松实现 Toast 的提示框
  6. JVM 性能调优监控工具
  7. java并发之CopyOnWirteArrayList
  8. ArrayList扩容
  9. C#类型的强制转换及隐式转换
  10. CEGUI添加自定义控件