嵌入式 linux驱动模块编译(初学者)

原创 2013年12月02日 14:55:35

linux 模块编译步骤(转)

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

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

第一步:准备源代码

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

mymodules.c

1. #include
2.#include
3. #include
4
5. MODULE_AUTHOR("Yu Qiang");
6. MODULE_LICENSE("GPL");
7
8. static int nbr = 10;
9. module_param(nbr, int, S_IRUGO);
10.
11. static int __init yuer_init(void)
12.{
13. int i;
14. for(i=0; i
15. {
16. printk(KERN_ALERT "Hello, How are you. %d/n", i);
17. }
18. return 0;
19.}
20.
21.static void __exit yuer_exit(void)
22.{
23. printk(KERN_ALERT"I come from yuer's module, I have beenunlad./n");
24.}
25.
26. module_init(yuer_init);
27. module_exit(yuer_exit);

我们的源文件就准备的差不多了,这就是一个linux下的模块的基本结构。第9行是导出我们的符号变量nbr。这样在你加载这个模块的时候可以动态修改这个变量的值。稍后将演示。yuer_init()函数将在模块加载的时候运行,通过输出的结果可以看到我们的模块是否加载成功。


第二步:编写Makefile文件

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

Makefile
obj-m := modules.o #要生成的模块名
modules-objs:= mymod.o#生成这个模块名所需要的目标文件

KDIR := /lib/modules/`uname -r`/build

PWD := $(shell pwd)

default:
make -C $(KDIR) M=$(PWD) modules

clean:
rm -rf *.o .* .cmd *.ko *.mod.c .tmp_versions

ARM平台

Makefile

obj-m += mymod.o
KDIR := /home/workspace2/kernel/linux-2.6.25 #如果是用于arm平台,则内核路径为arm内核的路径

PWD = $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o

在arm板上插入是

insmodmymod

如果出现以下错误
insmod:chdir(/lib/modules): No such file ordirectory
则运行
mkdir/lib/modules/2.6.25 (与arm内核版本相同)
并将mymod.ko文件复制到该目录下
cp mymod.ko/lib/modules/2.6.25
然后再执行 (insmod只在/lib/modules/2.6.25目录下查找相关驱动模块)
insmodmymod

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


第三步:编译模块

现在我们已经准备好了我们所需要的源文件和相应的Makefile。我们现在就可以编译了。在终端进入源文件目录输入make
运行结果:
make[1]: Entering directory`/usr/src/linux-headers-2.6.24-24-generic'
CC[M] /home/yuqiang/桌面/mymodule/mymodules.o
LD [M]/home/yuqiang/桌面/mymodule/modules.o
Building modules, stage2.
MODPOST 1modules
CC/home/yuqiang/桌面/mymodule/modules.mod.o
LD [M]/home/yuqiang/桌面/mymodule/modules.ko
make[1]: Leaving directory`/usr/src/linux-headers-2.6.24-24-generic'


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

从上面的编译中我可以看到。已经有一个modules.ko生成了。这就是我们的模块了。现在我们就可以来加载了。
首先在终端输入:sudo insmodmodules.ko
现在我们来看看我们的模块加载成功没有呢?
在终端输入:dmesg | tail -12这是查看内核输出信息的意思。tail -12 显示最后12条;
显示结果如下:
[17945.024417] sd 9:0:0:0: Attached scsi generic sg2 type 0
[18046.790019] usb 5-8: USB disconnect, address 9
[19934.224812] Hello, How are you. 0
[19934.224817] Hello, How are you. 1
[19934.224818] Hello, How are you. 2
[19934.224820] Hello, How are you. 3
[19934.224821] Hello, How are you. 4
[19934.224822] Hello, How are you. 5
[19934.224824] Hello, How are you. 6
[19934.224825] Hello, How are you. 7
[19934.224826] Hello, How are you. 8
[19934.224828] Hello, How are you. 9

看到了吧。我们的模块的初始化函数yuer_init();已经成功运行了。说明我们的模块已经加载成功;
现在我们再来卸载模块试试看。
在终端输入:sudo rmmodmodules
在终端输入:dmesg | tail-3
[19934.224826] Hello, How are you. 8
[19934.224828] Hello, How are you. 9
[20412.046932] I come from yuer's module, I have been unlad.

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


第五步:加载模块时传递参数
在终端输入:sudo insmod module_name.konbr=4
在终端输入:dmesg | tail-6
显示结果如下:
[20800.655694] Hello, How are you. 9
[21318.675593] I come from onefile module, I have been unlad.
[21334.425373] Hello, How are you. 0
[21334.425378] Hello, How are you. 1
[21334.425380] Hello, How are you. 2
[21334.425381] Hello, How are you. 3

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

如果我们的模块加载成功了。最后我们还可以通过modinfo来查看我们的模块信息。如下
在终端输入:sudo modinfomodules.ko
显示结果:
filename: modules.ko
license: GPL
author: Yu Qiang
srcversion: 20E9C3C4E02D130E6E92533
depends:
vermagic: 2.6.24-24-generic SMP mod_unload 586
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内核驱动之网络驱动(4)PHY芯片分析

一 以太网PHY芯片RTL8201CP分析 RTL8201CP是一个单端口的物理层收发器, 只有一个MII接口, 它可以通过网络变压器YL18-2050S或YT37-1107S接RJ45来实现全部...

海思hi3518用eclipse采用交叉编译器编译程序在海思开发板上运行

题记:在Linux下开发c/c++程序时,eclispe是一款不错的IDE软件,在用eclipse开发运行在Linux系统下的程序时,用到的编译工具链(toolchains)是linux gcc,而如...

linux驱动模块编译(初学者)

linux 模块编译步骤(转)     本文将直接了当的带你进入linux的模块编译。当然在介绍的过程当中,我也会添加一些必要的注释,以便初学者能够看懂。之所以要写这篇文章,主要是因为从书本...
  • rice19
  • rice19
  • 2014年10月16日 00:45
  • 284

linux驱动模块编译(初学者)

linux 模块编译步骤(转))    本文将直接了当的带你进入linux的模块编译。当然在介绍的过程当中,我也会添加一些必要的注释,以便初学者能够看懂。之所以要写这篇文章,主要是因为从书本上学的话,...

嵌入式linux驱动模块编写

注意:开发Arm平台的驱动,需要Arm平台的源码树; 注意:ARM平台的linux内核源码需要先编译,否则无法编译驱动; 一、第一种编译驱动方式,共6步 第1步:建立源码树 解压安装Linux...

Linux驱动模块编译进内核中

Linux驱动模块编译进内核中 BQ27501驱动编译进内核 一、       驱动程序编译进内核的步骤 在 linux 内核中增加程序需要完成以下三项工作: ...

加载Linux驱动模块读寄存器值

  • 2016年11月03日 20:06
  • 11KB
  • 下载

LINUX驱动模块编程入门

  • 2013年10月07日 00:04
  • 21KB
  • 下载

linux驱动模块加载出错insmod: error inserting './usb_driver.ko': -1 Unknown symbol in module

今天开始调试usb驱动,第一步加载模块部分就开始报错。网上检索,有位朋友总结一些类似情况。本人遇到的恰好是第二种情况,以前不太注意,没出错也就不追究,这次遇到了就一并把一些情况在此记上一笔。转载如下:...

Linux驱动模块初始教程

Linux驱动模块初始教程:一步一步,从helloworld到insmod->printk!!! 【0】笔者的配置环境 XP->VMWare 7.1->Ubuntu 9.04 【1】有必...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:嵌入式 linux驱动模块编译(初学者)
举报原因:
原因补充:

(最多只允许输入30个字)