关于linux内核模块Makefile的解析
转载:http://www.embeddedlinux.org.cn/html/yingjianqudong/201403/23-2820.html
Linux内核是一种单体内核,但是通过动态加载模块的方式,使它的开发非常灵活 方便。那么,它是如何编译内核的呢?我们可以通过分析它的Makefile入手。以下是 一个简单的hello内核模块的Makefile.
ifneq ($(KERNELRELEASE),)
obj-m := hello.o
else
KERNELDIR ?= /root/work/latest_codes/linux-stable
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean:
@rm -rf *.o *.mod.c *.mod.o *.ko *.order *.symvers .*.cmd .tmp_versions
endif
当我们写完一个hello模块,只要使用以上的makefile。然后make一下就行。
假设我们把hello模块的源代码放在/home/study/prog/mod/hello/下。
当我们在这个目录运行make时,make是怎么执行的呢?
LDD3第二章第四节“编译和装载”中只是简略地说到该Makefile被执行了两次,但是具体过程是如何的呢?
首
先,由于make
后面没有目标,所以make会在Makefile中的第一个不是以.开头的目标作为默认的目标执行。于是default成为make的目标。make会执
行 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules shell是make内部的函数,
假设当前内核版本是2.6.13-study,所以 $(shell uname -r) 的结果是 2.6.13-study 这里,实际运行的是
make -C /lib/modules/2.6.-study/build M=/home/study/prog/mod/hello/ modules
/lib /modules/2.6.13-study/build是一个指向内核源代码/usr/src/linux的符号链接。
可见,make执行了两次。
第一次执行时是读hello模块的源代码所在目录/home/s tudy/prog/mod/hello/下的Makefile。
第二次执行时是执行/usr/src/linux/下的Makefile时.
但是还是有不少令人困惑的问题: 1.这个KERNELRELEASE也很令人困惑,它是什么呢?在/home/study/prog/mod/he llo/Makefile中是没有定义这个变量的,所以起作用的是else…endif这一段。
不过,如果把hello模块移动到内核源代码中。例如放到/usr/src/linux/driver/中,
KERNELRELEASE就有定义了。在/usr/src/linux/Makefile中有 162 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION)
这时候,hello模块也不再是单独用make编译,而是在内核中用make modules进行
编译。用这种方式,该Makefile在单独编译和作为内核一部分编译时都能正常工作。
2.这个obj-m := hello.o什么时候会执行到呢? 在执行:
make -C /lib/modules/2.6.13-study/build M=/home/study/prog/mod/hello/ modules
时,make
去/usr/src/linux/Makefile中寻找目标modules:
.PHONY: modules modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) @echo ' Building modules, stage 2.'; $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
可以看出,分两个stage:
1.编译出hello.o文件。
2.生成hello.mod.o hello.ko
在这过程中,会调用 make -f scripts/Makefile.build
obj=/home/study/prog/mod/hello
而
在 scripts/Makefile.build会包含很多文件: -include .config include $(if $(wildcard $(obj)/Kbuild), $(obj)/Kbuild, $(obj)/Makefile) 其中就有/home/study/prog/mod/hello/Makefile 这时 KERNELRELEASE已经存在。
所以执行的是: obj-m:=hello.o
关于make modules的更详细的过程可以在scripts/Makefile.modpost文件的注释 中找到。如果想查看make的整个执行过程,
可以运行make -n。
关于linux内核模块Makefile的解析的更多相关文章
- Linux内核模块Makefile学习
在<Linux设备驱动程序>一书中读到的内核模块编译Makefile,不是非常理解,在查询很多资料后,在这里做个总结. 书中Makefile代码: ifneq ($(KERNELRELEA ...
- Linux笔记-Makefile伪指令解析
本文是我在博客里面找到的,觉得对makefile的伪指令介绍得非常详细了!也提到了伪指令为何要用.PHONY:来声明!希望我的这篇转过来的文章能够帮助大家理解makefile的伪指令! 我的理解: 拿 ...
- linux 内核模块makefile通用模板
ifneq ($(KERNELRELEASE),)# 在 mylist 后面添加需要编译的模块数量 mylist=hello.o a.o# 为每一个模块添加所需的文件 hello-objs := ma ...
- [ARM-LInux开发]linux设备驱动makefile入门解析
以下内容仅作参考,能力有限,如有错误还请纠正.对于一个普通的linux设备驱动模块,以下是一个经典的makefile代码,使用下面这个makefile可以完成大部分驱动的编译,使用时只需要修改一下要编 ...
- linux内核模块编译makefile
linux内核可加载模块的makefile 在开发linux内核驱动时,免不了要接触到makefile的编写和修改,尽管网上的makefile模板一大堆,做一些简单的修改就能用到自己的项目上,但是,对 ...
- linux中Makefile文件相关内容
第一章.概述什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional(专业)的程序员,m ...
- 5.linux内核模块基础,内核模块学习
linux内核模块基础 一.定义 Linux 内核的整体结构非常庞大,其包含的组件也非常多,如何使用这些组件呢: 方法 1:把所有的组件都编译进内核文件,即:zImage 或 bzImage,但这样会 ...
- Linux内核模块简介
一. 摘要 这篇文章主要介绍了Linux内核模块的相关概念,以及简单的模块开发过程.主要从模块开发中的常用指令.内核模块程序的结构.模块使用计数以及模块的编译等角度对内核模块进行介绍.在Linux系统 ...
- 【转载】Linux下makefile详解--跟我一起写 Makefile
概述 —— 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makef ...
随机推荐
- java、android 对比两个目录或文件是否是同一个目录或文件的方法
由于软链接及android的外部卡mount方式存在,导致一个文件夹可能同时有两个路径,如: /mnt/sdcard1 /storage/ext_sdcard ,如果通过某种方式(如moun ...
- T-SQL 运行时生成语句
运行时生成语句 1.用EXECUTE执行动态命令 EXECUTE命令可以执行存储过程.函数和动态的字符串命令.注意此语句的作用正如前面在介绍批处理时,如果批中的第一条语句是"EXECUTE存 ...
- T-SQL运算符
运算符 1.算术运算符 算术运算符 说明 + 加法 - 减法 * 乘法 / 除法 % 取模,两个整数相除后的余数 2.位运算符 位运算符 说明 &(与.and) 按位逻辑与运算 |(或.OR) ...
- oracle学习 十一 包+复合类型+自定义异常(持续更新)
在这里讲一下包的概念, 二话不说上个例子 包头: create or replace package pck_test is procedure proc_report_salary(name nva ...
- HDU 3364 Lanterns (高斯消元)
题意:有n个灯和m个开关,每个开关控制数个灯的状态改变,给出k条询问,问使灯的状态变为询问中的状态有多少种发法. 析:同余高斯消元法,模板题,将每个开关控制每个灯列成行列式,最终状态是结果列,同余高斯 ...
- Unity3d:延迟加载ScrollView的内容
问题描述:在一个scrollview中加载了大量的数据,有文字.图片.视频等等,首次加载的时候会很慢很卡,而且加载出来后,内存占用很大.解决方案1:思:固定一块区域,当物体滚动到这区域的时候再加载物体 ...
- js中的call及apply
http://www.zhihu.com/question/20289071 func1.call(this, arg1, arg2); 或者 func1.apply(this, [arg1, arg ...
- Linux下的TUN/TAP编程
linux下实现虚拟网卡我们在使用VMWARE的虚拟化软件时经常会发现它们能都能虚拟出一个网卡,貌似很神奇的技术,其实在Linux下很简单,有两种虚拟设 备,TUN时点对点的设备,tap表示以太网设备 ...
- springboot 学习笔记(一)
引子 最近在搞一个项目,走在科技前沿的师兄, 摒弃了公司老套的框架模式, 采用了springboot搭建新应用.看到如此简洁的代码 , 深受诱惑.趁周末闲余之时, 背晒阳光, 学起了springboo ...
- wp8 在OnBackKeyPress事件中调用MessageBox.Show()崩溃
今天写代码的时候遇到一个问题,在wp8中执行下面的代码后,弹出对话框后,停滞一段时间程序退出. protected override void OnBackKeyPress(CancelEventAr ...