Linux内核模块Makefile一个新手容易犯的错

又是受csdn bbs中一个帖子的启发,发现这个问题我之前也遇到过,所以就深入研究了一下。

以下是文件结构:

root@jusse ~/develop/kernel_module/helloworld# tree
.
├── hello.c
├── Makefile
├── mymax.c
└── mymax.h

0 directories, 4 files
hello.c:
#include 
#include 
#include "mymax.h"

MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
    printk("test1, Hello world\n");
    mymax();
    return 0;
}

static void hello_exit(void)
{
    printk("test1, Good bye\n");
}

module_init(hello_init);
module_exit(hello_exit);

mymax.c:

#include 
#include 

#include "mymax.h"
MODULE_LICENSE("Dual BSD/GPL");

void mymax(void)
{
    printk("test1, enter max\n");
}
EXPORT_SYMBOL(mymax);
mymax.h:

#include 
#include 

void mymax(void);

Makefile:

obj-m := hello.o
hello-objs := hello.o mymax.o
PWD := $(shell pwd)
all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
        rm *.o *.ko *~ *.mod.c *.order *.symvers
就是一个简单的helloworld内核模块,编译运行:
root@jusse ~/develop/kernel_module/helloworld# dmesg -c

root@jusse ~/develop/kernel_module/helloworld# make
make -C /lib/modules/3.13.0-36-generic/build M=/root/develop/kernel_module/helloworld modules
make[1]: Entering directory `/usr/src/linux-headers-3.13.0-36-generic'
make[2]: Circular /root/develop/kernel_module/helloworld/hello.o <- /root/develop/kernel_module/helloworld/hello.o dependency dropped.
  CC [M]  /root/develop/kernel_module/helloworld/mymax.o
  LD [M]  /root/develop/kernel_module/helloworld/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /root/develop/kernel_module/helloworld/hello.mod.o
  LD [M]  /root/develop/kernel_module/helloworld/hello.ko
make[1]: Leaving directory `/usr/src/linux-headers-3.13.0-36-generic'

root@jusse ~/develop/kernel_module/helloworld# insmod ./hello.ko

root@jusse ~/develop/kernel_module/helloworld# dmesg 

root@jusse ~/develop/kernel_module/helloworld# 
编译成功,加载模块成功,但是dmesg就是没有hello.c中用printk输出的日志,为啥?

起初我以为是printk的日志级别不对,调整到比较高的级别之后还是没有输出。

细心的朋友会看到make命令的输出结果中有一条日志:

make[2]: Circular /root/develop/kernel_module/helloworld/hello.o <- /root/develop/kernel_module/helloworld/hello.o dependency dropped. 

从字面上理解就是hello.o发生了循环依赖,被dropped掉了。

然后再来看看Makefile中的确是有两个hello.o,hello-objs这行指定hello依赖两个文件hello.o和mymax.o,而hello-objs中的hello就是obj-m这一行中的hello,所以也就是说hello.o依赖于hello.o和mymax.o,从而出现了循环依赖,所以就把hello.o dropped掉了,相当于这个Makefile:

obj-m := hello.o
hello-objs := mymax.o
PWD := $(shell pwd)
all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
        rm *.o *.ko *~ *.mod.c *.order *.symvers
把hello.c删除之后编译一下看看:
root@jusse ~/develop/kernel_module/helloworld# rm hello.c

root@jusse ~/develop/kernel_module/helloworld# cat Makefile 
obj-m := hello.o
hello-objs := mymax.o
PWD := $(shell pwd)
all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
        rm *.o *.ko *~ *.mod.c *.order *.symvers

root@jusse ~/develop/kernel_module/helloworld# make
make -C /lib/modules/3.13.0-36-generic/build M=/root/develop/kernel_module/helloworld modules
make[1]: Entering directory `/usr/src/linux-headers-3.13.0-36-generic'
  CC [M]  /root/develop/kernel_module/helloworld/mymax.o
  LD [M]  /root/develop/kernel_module/helloworld/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /root/develop/kernel_module/helloworld/hello.mod.o
  LD [M]  /root/develop/kernel_module/helloworld/hello.ko
make[1]: Leaving directory `/usr/src/linux-headers-3.13.0-36-generic'

root@jusse ~/develop/kernel_module/helloworld# ls
hello.ko  hello.mod.c  hello.mod.o  hello.o  Makefile  modules.order  Module.symvers  mymax.c  mymax.h  mymax.o

照样能编译成功,所以问题的原因找到了,那只要修改一下Makefile之后就可以了:

obj-m := world.o
world-objs := hello.o mymax.o
PWD := $(shell pwd)
all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
        rm *.o *.ko *~ *.mod.c *.order *.symvers

编译运行:

root@jusse ~/develop/kernel_module/helloworld# ls

hello.c  Makefile  mymax.c  mymax.h

root@jusse ~/develop/kernel_module/helloworld# cat Makefile 
obj-m := world.o
world-objs := hello.o mymax.o
PWD := $(shell pwd)
all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
        rm *.o *.ko *~ *.mod.c *.order *.symvers

root@jusse ~/develop/kernel_module/helloworld# make
make -C /lib/modules/3.13.0-36-generic/build M=/root/develop/kernel_module/helloworld modules
make[1]: Entering directory `/usr/src/linux-headers-3.13.0-36-generic'
  CC [M]  /root/develop/kernel_module/helloworld/hello.o
  CC [M]  /root/develop/kernel_module/helloworld/mymax.o
  LD [M]  /root/develop/kernel_module/helloworld/world.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /root/develop/kernel_module/helloworld/world.mod.o
  LD [M]  /root/develop/kernel_module/helloworld/world.ko
make[1]: Leaving directory `/usr/src/linux-headers-3.13.0-36-generic'

root@jusse ~/develop/kernel_module/helloworld# insmod ./world.ko

root@jusse ~/develop/kernel_module/helloworld# dmesg 
[4556877.286444] test1, Hello world
[4556877.286449] test1, enter max

root@jusse ~/develop/kernel_module/helloworld#
从dmesg输出中可以看出成功了。

结论:Makefile中obj-m指定的模块名和*-objs指定的依赖文件名不能相同,否则就会出现循环依赖。

至于make如何检测循环依赖,感兴趣的朋友可以看看make源码文件remake.c中的一个函数update_file_1,这个函数每更新一个文件时都会在struct file结构中打上一个updating标记,更新文件期间也会检测依赖的文件看看updating标记是否已经打过了,如果发现循环依赖(打过标记:updating==1)那就直接忽略掉那个文件了。大概就是这样,代码就不贴了。

你可能感兴趣的:(linux)