以下内容仅作参考,能力有限,如有错误还请纠正。
对于一个普通的linux设备驱动模块,以下是一个经典的makefile代码,使用下面这个makefile可以
完成大部分驱动的编译,使用时只需要修改一下要编译生成的驱动名称即可。只需修改obj-m的值。

ifneq ($(KERNELRELEASE),)
obj-m:=hello.o
else
#generate the path
CURRENT_PATH:=$(shell pwd)
#the absolute path
LINUX_KERNEL_PATH:=/lib/modules/$(shell uname -r)/build
#complie object
default:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
endif

说明:
当我们在模块的源代码目录下运行make时,make是怎么执行的呢?
假设模块的源代码目录是/home/study/prog/mod/hello/下。
先说明以下makefile中一些变量意义:
(1)KERNELRELEASE在linux内核源代码中的顶层makefile中有定义
(2)shell pwd会取得当前工作路径
(3)shell uname -r会取得当前内核的版本号
(4)LINUX_KERNEL_PATH变量便是当前内核的源代码目录。
关于linux源码的目录有两个,分别为"/lib/modules/$(shell uname -r)/build"和"/usr/src/linux-header-$(shell
uname -r)/",
但如果编译过内核就会知道,usr目录下那个源代码一般是我们自己下载后解压的,而lib目录下的则是在编译时自动copy过去的,
两者的文件结构完全一样,因此有时也将内核源码目录设置成/usr/src/linux-header-$(shell uname -r)/。关于内核源码目录
可以根据自己的存放位置进行修改。
(5)make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
这就是编译模块了:首先改变目录到-C选项指定的位置(即内核源代码目录),其中保存有内核的顶层makefile;
M=选项让该makefile在构造modules目标之前返回到模块源代码目录;然后,modueles目标指向obj-m变量中设定的模块;
在上面的例子中,我们将该变量设置成了hello.o。

按照顺序分析以下make的执行步骤:
在模块的源代码目录下执行make,此时,宏“KERNELRELEASE”没有定义,因此进入else。
由于make 后面没有目标,所以make会在Makefile中的第一个不是以.开头的目标作为默认的目标执行。
于是default成为make的目标。
make会执行 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules ,假设当前内核版本是2.6.13-study,
所以$(shell uname -r)的结果是 2.6.13-study ,这里实际运行的是
make -C /lib/modules/2.6.13-study/build M=/home/study/prog/mod/hello/ modules

-C 表示到存放内核的目录执行其makefile,在执行过程中会定义KERNELRELEASE,
然后M=$(CURDIR)表示返回到当前目录,再次执行makefile,modules表示编译成模块的意思。
而此时KERNELRELEASE已定义,则会执行obj-m += hello.o,表示会将hello_world.o目标编译成.ko模块。
若有多个源文件,则采用如下方法:
obj-m := hello.o
hello-objs := file1.o file2.o file3.o
关于make modules的更详细的过程可以在内核源码目录下的scripts/Makefile.modpost文件的注释 中找到。

如果把hello模块移动到内核源代码中。例如放到/usr/src/linux/driver/中, KERNELRELEASE就有定义了。
在/usr/src/linux/Makefile中有KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION)。

这时候,hello模块也不再是单独用make编译,而是在内核中用make modules进行编译,此时驱动模块便和内核编译在一起。

关于内核模块编译可以参考另外一篇文章:linux内核模块编译基础知识

转载请注明:http://blog.csdn.net/shanzhizi

[ARM-LInux开发]linux设备驱动makefile入门解析的更多相关文章

  1. Linux 设备驱动开发 —— platform设备驱动应用实例解析

    前面我们已经学习了platform设备的理论知识Linux 设备驱动开发 —— platform 设备驱动 ,下面将通过一个实例来深入我们的学习. 一.platform 驱动的工作过程 platfor ...

  2. Linux和Windows设备驱动架构比较

    毕业后一直在学操作系统, 有时候觉得什么都懂了,有时候又觉得好像什么都不懂,但总体来说自认为对操作系统实现机制的了解比周围的人还是要多一些.去年曾花了几个星期的晚上时间断断续续翻译了这篇对Linux和 ...

  3. Linux下 USB设备驱动分析(原创)

    之前做过STM32的usb HID复合设备,闲来看看linux下USB设备驱动是怎么一回事, 参考资料基于韦东山JZ2440开发板,以下,有错误欢迎指出. 1.准备知识 1.1USB相关概念: USB ...

  4. Linux的总线设备驱动模型

    裸机编写驱动比较自由,按照手册实现其功能即可,每个人写出来都有很大不同: 而Linux中还需要按照Linux的驱动模型来编写,也就是需要按照"模板"来写,写出来的驱动就比较统一. ...

  5. linux设备驱动编写入门

    linux设备驱动是什么,我个人的理解是liunx有用户态和内核态,用户空间中是不能直接对设备的外设进行使用而内核态中却可以,这时我们需要在内核空间中将需要的外设驱动起来供用户空间使用.linux的驱 ...

  6. 芯灵思SinlinxA33开发板 Linux平台总线设备驱动

    1.什么是platform(平台)总线? 相对于USB.PCI.I2C.SPI等物理总线来说,platform总线是一种虚拟.抽象出来的总线,实际中并不存在这样的总线. 那为什么需要platform总 ...

  7. Linux实现字符设备驱动的基础步骤

    Linux应用层想要操作kernel层的API,比方想操作相关GPIO或寄存器,能够通过写一个字符设备驱动来实现. 1.先在rootfs中的 /dev/ 下生成一个字符设备.注意主设备号 和 从设备号 ...

  8. Linux中总线设备驱动模型及平台设备驱动实例

    本文将简要地介绍Linux总线设备驱动模型及其实现方式,并不会过多地涉及其在内核中的具体实现,最后,本文将会以平台总线为例介绍设备和驱动程序的实现过程. 目录: 一.总线设备驱动模型总体介绍及其实现方 ...

  9. Linux中LCD设备驱动-framebuffer(帧缓冲)【】

    转自:https://blog.csdn.net/linux_devices_driver/article/details/7079442 1.framebuffer 帧缓冲     帧缓冲(fram ...

随机推荐

  1. Spring全家桶相关文章汇总(Spring,SpringBoot,SpringData,SpringCloud)

      因为Spring框架包含的组件比较多,写的博客内容也比较多,虽然有分专栏但是依然不方便查找,所以专门用一篇文章来记录相关文章,会不定期更新. 一.Spring 1.基础内容 Spring介绍 Sp ...

  2. Synchronized性质

    Synchronized可重入性质 * 什么是可重入:指的是同一线程的外层函数获得锁之后,内层函数可以直接再次获取该锁,而不是释放当前的锁去重新获取一个锁,这是它的一个优点 * 好处:避免死锁,提升封 ...

  3. 【C/C++】变量

    变量定义就是告诉编译器在何处创建变量的存储,以及如何创建变量的存储.变量定义指定一个数据类型,并包含了该类型的一个或多个变量的列表. 变量声明向编译器保证变量以给定的类型和名称存在,这样编译器在不需要 ...

  4. Python研究

    听说Python是种高级语言,故打算研究一下,看看高级在哪 学习资源:https://www.liaoxuefeng.com/wiki/1016959663602400 由于上面所示的网站对Pytho ...

  5. JavaScript 箭头函数

    ES6新标准增加了一种新的函数,箭头函数. x=>x*x 相当于: function (x){ return x*x; } 如果参数不是一个,就需要用括号()括起来: // 两个参数:var t ...

  6. [WEB安全]源码泄露总结

    原文链接:https://blog.csdn.net/qq_36869808/article/details/88895109 源码泄露总结: svn源码泄露:https://blog.csdn.ne ...

  7. Sequelize 数据类型

    Sequelize.STRING // VARCHAR(255)Sequelize.STRING(1234) // VARCHAR(1234)Sequelize.STRING.BINARY // VA ...

  8. adb: failed to install app-debug.apk: Failure [INSTALL_FAILED_ABORTED: User rejected permissions]

    一.使用adb 的usb真机调试,安装错误: adb: failed to install app-debug.apk: Failure [INSTALL_FAILED_ABORTED: User r ...

  9. [Web 测试] Jest单元测试的几个指标

    三个参数代表什么? %stmts是语句覆盖率(statement coverage):是不是每个语句都执行了? %Branch分支覆盖率(branch coverage):是不是每个if代码块都执行了 ...

  10. Mysql:设置主键自动增长起始值

    比较郁闷昨天在家使用‘alter table `tablename` AUTO_INCREMENT=10000;’怎么也不起效,但是今天下班时间公司一同事尝试了一下就可以了.搞不明白自己当时是怎么操作 ...