本文将直接了当的带你进入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 been unlad./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板上插入是

insmod mymod 

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

现在我来说明一下这个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, stage 2.
    MODPOST 1 modules
    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 insmod modules.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 rmmod modules
在终端输入: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.ko nbr=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 modinfo modules.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相关的专家,我只是一个普通的linux相关开发人员(在读),我的目的也很简单,就是想给大家介绍一个方法,希望大家在学习的时候不要走过多的弯路。由于个人能力所限难免存在错误和缺点,所以请不要介意,如有发现请提出,我立即修改。方便大家学习

linux下 驱动模块编译步骤的更多相关文章

  1. ACE-6.1.0 linux 下的编译与安装步骤

    ACE-6.1.0 linux 下的编译与安装步骤  引用至http://www.cnblogs.com/liangxiaxu/archive/2013/03/07/2948417.html 1.从  ...

  2. 从四个问题透析Linux下C++编译&链接

    摘要:编译&链接对C&C++程序员既熟悉又陌生,熟悉在于每份代码都要经历编译&链接过程,陌生在于大部分人并不会刻意关注编译&链接的原理.本文通过开发过程中碰到的四个典型 ...

  3. LINUX下文件编译

    body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...

  4. FFmpeg在Linux下安装编译过程

    转载请把头部出处链接和尾部二维码一起转载,本文出自:http://blog.csdn.net/hejjunlin/article/details/52402759 今天介绍下FFmpeg在Linux下 ...

  5. Linux下安装jdk8步骤详述(转载)

    Linux下安装jdk8步骤详述 原文地址:http://www.cnblogs.com/shihaiming/p/5809553.html 作为Java开发人员,在Linux下安装一些开发工具是必备 ...

  6. Linux下nginx编译安装教程和编译参数详解

    这篇文章主要介绍了Linux下nginx编译安装教程和编译参数详解,需要的朋友可以参考下 一.必要软件准备1.安装pcre 为了支持rewrite功能,我们需要安装pcre 复制代码代码如下: # y ...

  7. linux下将编译错误输出到一个文本文件

    linux下将编译错误输出到一个文本文件 command > filename 把把标准输出重定向到一个新文件中 command > > filename 把把标准输出重定向到一个文 ...

  8. [转]Linux下g++编译与使用静态库(.a)和动态库(.os) (+修正与解释)

    在windows环境下,我们通常在IDE如VS的工程中开发C++项目,对于生成和使用静态库(*.lib)与动态库(*.dll)可能都已经比较熟悉,但是,在linux环境下,则是另一套模式,对应的静态库 ...

  9. Apache Linux下Apache安装步骤

    Apache简介         Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源码的网页服务器,可以在大多数计算机操作系统中运行,由于其多平台和安全性被广 ...

随机推荐

  1. ES6——新增数据结构Set与Map的用法

    ES6 提供了新的数据结构 Set以及Map,下面我们来一一讲解. 一.Set 特性 似于数组,但它的一大特性就是所有元素都是唯一的,没有重复. 我们可以利用这一唯一特性进行数组的去重工作. 1.单一 ...

  2. Spring5源码解析6-ConfigurationClassParser 解析配置类

    ConfigurationClassParser 在ConfigurationClassPostProcessor#processConfigBeanDefinitions方法中创建了Configur ...

  3. 【Java 基础】你听说过JMX么

    目录 什么是JMX 相关概念 MBean代码示例 MBean本地连接 MBean远程连接 通过Spring发布MBean 消息订阅发布 参考 什么是JMX JMX(Java管理扩展),是一套给应用程序 ...

  4. ABAP实现Blowfish加密算法

    看到SAP社区中有人问是否存在ABAP实现的Blowfish加密算法,无人回答.于是动手实现了一个blowfish-abap.通过blowfish-abap可以在SAP系统中使用Blowfish对数据 ...

  5. 搭建YUM本地仓库

    本文介绍如何利用CentOS 7 ISO光盘镜像搭建YUM本地仓库. 环境准备: (1)VMware15.5版本虚拟机 (2)CentOS-7-x86_64-DVD-1908光盘镜像文件 1. 搭建Y ...

  6. Python_三元运算与lambda表达式

    [是什么] 三元运算是if...else...的简化版,lambda表达式是函数的简化版 三元运算(三目运算) # 判断两个数中的较大者 fun(a1,a2): return a1 if a1> ...

  7. OCPC(Optimized Cost per Click)[Paper笔记]

    背景 在线广告中,广告按照CPM排序,排在前面的广告竞争有限广告位(截断).其中,CPM=bid*pctr.注GSP二价计费的,按照下一位bid计费.适当调整bid,可以提高竞价的排名,从而获得展现的 ...

  8. Ubuntu php + apache

    Ubuntu 环境: 问题1: apache 不能解析 *.php 文件 安装apache的扩展模块 :  apt-get install libapache2-mod-php 问题2 : 客户端访问 ...

  9. 1、Struts2基本入门

    一.了解了这几个主要的优点,会促使你考虑使用Struts2 : 1.POJO表单及POJO操作 - Struts2 去除掉了Struts框架中的Action Forms部分.在Struts2框架下,你 ...

  10. win10系统 plsql developer启动慢

    win10系统plsql启动慢一般原因是plsql打印设置的问题,若默认打印机设置为网络上某一位置的打印机,则plsql启动时会去寻找该打印机,导致启动很慢. 解决办法1 直接禁止print spoo ...