一、引文

前篇博文《Makefile之Linux内核模块的Makefile写法分析》,介绍了Linux编译生成内核驱动模块的Makefile的写法,但最近在DVSDK下使用Linux2.6.37生成PowerVR 2D/3D加速器的内核模块时,发现其Makefile中并未向其他内核模块Makefile指定内核模块的目标对象(obj-m:= pvrsrvkm.o),但最后却在模块目录下生成了pvrsrvkm.ko内核模块。一开始感觉非常奇怪,决定把其中的原由弄明白,并将该过程记录了下来。

/**********************************************************************************************************************************/

原创作品,转载时请务必以超链接形式标明文章原始出处:http://blog.csdn.net/gqb666/article/details/9054413,作者:gqb666  

    /**********************************************************************************************************************************/

二、追踪

既然模块文件夹下的Makefile文件没有指定,那肯定会有其他有相同功能的文件会指定内核模块的目标对象pvrsrvkm.o,于是查看该目录下的文件,果然在Kbuid文件发现有与Makefile文件类似的内容,将Kbuild的关键内容贴出来:

obj-m	:= pvrsrvkm.o
FILES := \
services4/srvkm/common/queue.c \
……
services4/system/$(TI_PLATFORM)/sysconfig.c \ EXTRA_CFLAGS += -I$(src)/include4
EXTRA_CFLAGS += -I$(src)/services4/include
……
EXTRA_CFLAGS += -I$(src)/services4/srvkm/bridged/sgx
EXTRA_CFLAGS += $(ALL_CFLAGS) pvrsrvkm-y := $(FILES:.c=.o)
ifeq ($(TI_PLATFORM),ti8168)
obj-y := services4/3rdparty/dc_ti8168_linux/
else
obj-y := services4/3rdparty/dc_omap3430_linux/
endif
obj-y += services4/3rdparty/bufferclass_ti/

三、真相:Linux Kbuild子系统

实际上从Linux内核2.6开始,Linux内核的编译采用Kbuild系统,这同过去的编译系统有很大的不同, 尤其对于Linux内核驱动模块的编译。在新的系统下,Linux编译系统会两次扫描Linux的Makefile:首先编译系统会读取Linux内核顶层的Makefile,然后根据读到的内容第二次读取Kbuild的Makefile来编译Linux内核。

查看内核文档:../Documentation/kbuild/makefiles.txt我们可以获取到以下信息:
Linux内核Makefile分类(五类)
·Kernel Makefile 
Kernel Makefile位于Linux内核源代码的顶层目录,也叫 Top Makefile。它主要用于指定编译Linux Kernel目标文件(vmlinux)和模块(module)。这编译内核或模块是,这个文件会被首先 读取,并根据读到的内容配置编译环境变量。对于内核或驱动开发人员来说,这个文件几乎不用任何修改。

·.config

此文件为Kbuid构建子系统从..\arch\arm\configs目录下读了内核的相关配置或者通过make menuconfig而生成的内核临时配置文件。
·sripts/Makefile.*

sripts/Makefile.* 包含了使用Kbuild Makefile子系统所用的所有规则的定义。
·Kbuild Makefile 
     Kbuild系统使用Kbuild Makefile来编译内核或模块。当Kernel Makefile被解析完成后,Kbuild会读取相关的Kbuild Makefile进行内核或模块的编译。Kbuild Makefile有特定的语法指定哪些编译进内核中、哪些编译为模块、及对应的源文件是什么等。内核及驱动开发人员需要编写这个Kbuild Makefile文件。
·ARCH Makefile 
ARCH Makefile位于ARCH/$(ARCH)/Makefile,是系统对应平台的Makefile。Kernel Top Makefile会包含这个文件来指定平台相关信息。只有平台开发人员会关心这个文件。
    Kbuild Makefile的文件名不一定是Makefile,尽管推荐使用Makefile这个名字。 大多的Kbuild文件的名字都是Makefile。为了与其他Makefile文件相区别,你也可以指定Kbuild Makefile的名字为Kbuild。而且如果“Makefile”和“Kbuild”文件同时存在,则Kbuild系统会使用“Kbuild”文件。

上面的几句来自对内核文档的翻译,然而上面标红的一段话,经过验证感觉不太准确,博主将模块目录中的Makefile删除,仅留下Kbuild文件却模块编译会出错。这到底是怎么回事呢?还是跟下代码流程来分析。

四、根本解决(Linux Kbuild 工作原理)

实际上执行了make命令后,Kbuild子系统还是要找到模块目录下的Makefile,如下:

all:
$(MAKE) -C $(KERNELDIR) M=`pwd` $*

其中 KERNELDIR 变量值为内核源码目录根目录

可见,Kbuild子系统将进行内核源码根目录下去执行make,并将模块所在的目录名以参数的形式传进去。

实际上该过程总共分为两个stage:

1.编译出pvrsrvkm.o文件。

2.生成pvrsrvkm.mod.o pvrsrvkm.ko,并内核模块文件拷加原模块目录。见如下打印log:

make -C /home/ss/ti-dvsdk_dm3730-evm_4_02_00_06/psp/linux-2.6.32-psp03.00.01.06.sdk M=`pwd`
Building objects, stage 1.
make[3]: Entering directory `/home/ss/develop_environment/v2/sys/dvsdk/ti-dvsdk_dm3730-evm_4_02_00_06/psp/linux-2.6.32-psp03.00.01.06.sdk'
……
LD [M] /home/ss/develop_environment/v2/sys/dvsdk/ti-dvsdk_dm3730-evm_4_02_00_06/omap35x_graphics_sdk_4.00.00.01/GFX_Linux_KM/pvrsrvkm.o
Building modules, stage 2.
MODPOST 3 modules
CC /home/ss/develop_environment/v2/sys/dvsdk/ti-dvsdk_dm3730-evm_4_02_00_06/omap35x_graphics_sdk_4.00.00.01/GFX_Linux_KM/pvrsrvkm.mod.o
LD [M] /home/ss/develop_environment/v2/sys/dvsdk/ti-dvsdk_dm3730-evm_4_02_00_06/omap35x_graphics_sdk_4.00.00.01/GFX_Linux_KM/pvrsrvkm.ko
……
make[3]: Leaving directory `/home/ss/develop_environment/v2/sys/dvsdk/ti-dvsdk_dm3730-evm_4_02_00_06/psp/linux-2.6.32-psp03.00.01.06.sdk'
make[2]: Leaving directory `/home/ss/develop_environment/v2/sys/dvsdk/ti-dvsdk_dm3730-evm_4_02_00_06/omap35x_graphics_sdk_4.00.00.01/GFX_Linux_KM'
copying the sgx kernel modules to appropriate folder...
building devmem2...
make -C /home/ss/ti-dvsdk_dm3730-evm_4_02_00_06/omap35x_graphics_sdk_4.00.00.01/tools/devmem2 clean && make -C /home/ss/ti-dvsdk_dm3730-evm_4_02_00_06/omap35x_graphics_sdk_4.00.00.01/tools/devmem2 && make -C /home/ss/ti-dvsdk_dm3730-evm_4_02_00_06/omap35x_graphics_sdk_4.00.00.01/tools/devmem2 install
make[2]: Entering directory `/home/ss/develop_environment/v2/sys/dvsdk/ti-dvsdk_dm3730-evm_4_02_00_06/omap35x_graphics_sdk_4.00.00.01/tools/devmem2'
rm -rf ./Obj *.o
make[2]: Leaving directory `/home/ss/develop_environment/v2/sys/dvsdk/ti-dvsdk_dm3730-evm_4_02_00_06/omap35x_graphics_sdk_4.00.00.01/tools/devmem2'
make[2]: Entering directory `/home/ss/develop_environment/v2/sys/dvsdk/ti-dvsdk_dm3730-evm_4_02_00_06/omap35x_graphics_sdk_4.00.00.01/tools/devmem2'
mkdir -p ./Obj
……
arm-none-linux-gnueabi-g++ -o ./Obj/devmem2 ./Obj/devmem2.o -lm -ldl -L/lib -Wl
/usr/local/arm/arm-2009q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/../../../../arm-none-linux-gnueabi/bin/ld: warning: library search path "/lib" is unsafe for cross-compilation
make[2]: Leaving directory `/home/ss/develop_environment/v2/sys/dvsdk/ti-dvsdk_dm3730-evm_4_02_00_06/omap35x_graphics_sdk_4.00.00.01/tools/devmem2'
make[2]: Entering directory `/home/ss/develop_environment/v2/sys/dvsdk/ti-dvsdk_dm3730-evm_4_02_00_06/omap35x_graphics_sdk_4.00.00.01/tools/devmem2'
cp ./Obj/devmem2 ../../targetfs/
make[2]: Leaving directory `/home/ss/develop_environment/v2/sys/dvsdk/ti-dvsdk_dm3730-evm_4_02_00_06/omap35x_graphics_sdk_4.00.00.01/tools/devmem2'
make[1]: Leaving directory `/home/ss/develop_environment/v2/sys/dvsdk/ti-dvsdk_dm3730-evm_4_02_00_06/omap35x_graphics_sdk_4.00.00.01'

stage 1:

内核Makefile根据时间戳进行比较看哪些目标文件需要编译,这个过程将生成pvrsrvkm.o文件。

stage 2:

这个obj-m :pvrsrvkm.o什么时候会执行到呢?

在执行:

$(MAKE) -C $(KERNELDIR) M=`pwd` $*

时,Kbuild去内核根目录下的Makefile中寻找目标modules,代码贴上:

PHONY += modules
modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
$(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
@$(kecho) ' Building modules, stage 2.';
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild

在这过程中,会调用

$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost

而在 scripts/Makefile.modpost中会包含很多文件如:

include $(if $(wildcard $(KBUILD_EXTMOD)/Kbuild), \
$(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile)

由上面可看出:内核根目录Makefile相当于以头文件的形式包含了模块目录下的Kbuild文件和Makefile

所以执行的是:obj-m:=pvrsrvkm.o

进而pvrsrvkm.mod.o pvrsrvkm.ko也就生成了,最后又将pvrsrvkm.ko内核模块拷贝到原模块目录。

Linux Kbuild工作原理分析(以DVSDK生成PowerVR显卡内核模块为例)的更多相关文章

  1. Azure WAF防火墙工作原理分析和配置向导

    Azure WAF工作原理分析和配置向导 本文博客地址为:http://www.cnblogs.com/taosha/p/6716434.html ,转载请保留出处,多谢! 本地数据中心往云端迁移的的 ...

  2. getaddrinfo工作原理分析

    getaddrinfo工作原理分析 将域名解析成ip地址是所有涉及网络通讯功能程序的基本步骤之一,常用的两个接口是gethostbyname和getaddrinfo,而后者是Posix标准推荐在新应用 ...

  3. SPI协议及工作原理分析

    说明.文章摘自:SPI协议及其工作原理分析 http://blog.csdn.net/skyflying2012/article/details/11710801 一.概述. SPI, Serial ...

  4. Security:蠕虫的行为特征描述和工作原理分析

    ________________________ 参考: 百度文库---蠕虫的行为特征描述和工作原理分析 http://wenku.baidu.com/link?url=ygP1SaVE4t4-5fi ...

  5. Hadoop生态圈-Zookeeper的工作原理分析

    Hadoop生态圈-Zookeeper的工作原理分析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   无论是是Kafka集群,还是producer和consumer都依赖于Zoo ...

  6. 原理剖析-Netty之服务端启动工作原理分析(下)

    一.大致介绍 1.由于篇幅过长难以发布,所以本章节接着上一节来的,上一章节为[原理剖析(第 010 篇)Netty之服务端启动工作原理分析(上)]: 2.那么本章节就继续分析Netty的服务端启动,分 ...

  7. AQS工作原理分析

      AQS工作原理分析 一.大致介绍1.前面章节讲解了一下CAS,简单讲就是cmpxchg+lock的原子操作:2.而在谈到并发操作里面,我们不得不谈到AQS,JDK的源码里面好多并发的类都是通过Sy ...

  8. 结合 category 工作原理分析 OC2.0 中的 runtime

    绝大多数 iOS 开发者在学习 runtime 时都阅读过 runtime.h 文件中的这段代码: struct objc_class { Class isa  OBJC_ISA_AVAILABILI ...

  9. tcpkill工作原理分析

    此文已由作者张耕源授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 日常工作生活中大家在维护自己的服务器.VPS有时会碰到这样的情况:服务器上突然出现了许多来自未知ip的网络连 ...

随机推荐

  1. 全局获取Context的技巧

    全局获取Context的技巧 在android开发中,非常多地方都要用到Context上下文这个类对象,比方:弹出 Toast 的时候须要.启动活动的时候须要.发送广播的时候须要.操作数据库的时候须要 ...

  2. iOS开发- 打包ipa,让别人设备安装你的App

    一般在接外包的时候, 通常第三方须要安装你的app进行測试(这时候你的app肯定是还没传到app store之前). 这样的情况下.假设是企业账号就好办了, 随便安装.. 可是个人开发人员账号呢? 假 ...

  3. 【Eclipse】Tomcat 一直处于starting状态,项目却已成功启动

    是因为Eclipse里面设置了代理.preference-network connections-activity provider-direct-应用.重启tomcat即可.

  4. Java面试题集(1-50)

    下面的内容是对网上原有的面试题集及答案进行了全面修订之后的内容(原来的题目有很多重复无用的题以及错误的答案),参照了JDK最新版本,删除了重复题目以及EJB2.x等无用内容,补充最新面试题.知识点巩固 ...

  5. [转] iOS (OC) 中 KVC 与 KVO 理解

    转自: http://magicalboy.com/kvc_and_kvo/ KVC 与 KVO 是 Objective C 的关键概念,个人认为必须理解的东西,下面是实例讲解. Key-Value ...

  6. php开启虚拟域名功能

    1.开启apache的mod_rewrite功能 关闭注释 LoadModule rewrite_module modules/mod_rewrite.so 2.引入http-vhosts.conf文 ...

  7. Ubuntu14.04 Y460闪屏问题解决方案

    我的笔记本是联想Y460,安装了Ubuntu之后发现屏幕闪烁移位,而且在使用IDE的时候出现无法输入中文等问题,其实是显卡驱动的问题,N卡官网给的驱动不好用,尝试使用大黄蜂 参考:https://wi ...

  8. 显示器中关于HS,VS,HBP,VBP参数浅析

    先来解释几个缩写的含义 HSYNC : 水平同步信号(horizontal synchronization signal) VSYNC :  垂直同步(Vertical Sync):场同步 FR : ...

  9. Android常用动画Frame-By-Frame Animations的使用

    在Android的动画中有一种叫做Frame by Frame 的动画效果,就是跟Flash播放一样,是一帧一帧地显示,如果动画是连续并且有规律的话,就跟播放视频一样. 首先在drawable目录下添 ...

  10. 一步一步重写 CodeIgniter 框架 (5) —— 实现Controller,并加载Model

    CodeIgniter 框架采用MVC模式,而MVC模式中起纽带作用的就是C(控制器),在控制器的中通过加载模型获得数据,将数据传到视图中进行展示.本课将实现在控制器中加载模型. 1. 控制器的实现 ...