Chinaunix首页 | 论坛 | 博客
  • 博客访问: 187854
  • 博文数量: 40
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 418
  • 用 户 组: 普通用户
  • 注册时间: 2013-06-26 22:37
文章存档

2015年(4)

2014年(27)

2013年(9)

我的朋友

分类: LINUX

2013-12-20 01:01:36

      通常,一个linux内核模块的makefile写法都是如下所示:

点击(此处)折叠或打开

  1. # If KERNELRELEASE is defined, we've been invoked from the
  2. # kernel build system and can use its language.
  3. ifneq ($(KERNELRELEASE),)
  4.     obj-m := hello.o
  5. # Otherwise we were called directly from the command
  6. # line; invoke the kernel build system.
  7. else
  8.     KERNELDIR ?= /lib/modules/$(shell uname -r)/build
  9.     PWD := $(shell pwd)
  10. default:
  11.     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
  12. endif
      我一直都很好奇,为什么要用if将代码分开,而不是干脆使用里面的所有代码呢?而且看起来if-else将其分割成两部分,default目标也不知道将要编译成的模块的名字啊,但是编译模块时又能得到我们所指定的模块名字,那么这又是为什么呢?
     最近开始阅读《Linux设备驱动》第三版,在第二章“building and installing modules”(英文版P24),终于找到了答案。
    原来是因为kbuild系统的设计,首先在源码目录下,$(KERNELRELEASE)没有定义,所以makefile中第二行:
  1. ifneq ($(KERNELRELEASE),)
    不满足条件,所以走else分支,声明了$KERNELDIR以及$PWD变量并在default中开始编译。-C选项跳转进入内核树目录,kbuild会重新读取一次makefile,此时$(KERNELRELEASE)已经定义,于是声明内核模块名字:
  1.     obj-:= hello.o
  读取到正确的模块名字后,重新开始编译构建,并得到最终的模块。
  综上所述,所有的这一切都归功于内核的kbuild系统,其最巧妙的地方在于两次读取makefile,从而使我们平常认为不可能同时作用的ifneq-else-endif结构中的两个分支中的语句同时发生作用,也就相当于没有了这个ifneq-else-endif结构的限制。于是自然就能得到所需要的全部信息。
  而这,就是内核kbuild系统的特殊机制。
阅读(3900) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~