Makefile 无效的模块格式

Makefile 无效的模块格式,makefile,linux-kernel,kernel-module,Makefile,Linux Kernel,Kernel Module,Makefile是传统格式(使用(CC))和模块构建系统格式的混合体“make-C/lib/modules/$(shell uname-r)/build M=$(PWD)模块” 系统为1.6.18-194.el5 x86_64。同样的Makefile在i386机器中使用时也可以正常工作 知道要调查什么吗?谢谢 #Makefile(CC)和内核模块构建系统的混合 CFLAGS+=-D“KBUILD\u STR(s)=\\s“-D”KBUILD\u BASENAME=KBUILD\u STR(您好

Makefile是传统格式(使用(CC))和模块构建系统格式的混合体
“make-C/lib/modules/$(shell uname-r)/build M=$(PWD)模块”

系统为1.6.18-194.el5 x86_64。同样的Makefile在i386机器中使用时也可以正常工作

知道要调查什么吗?谢谢


#Makefile(CC)和内核模块构建系统的混合
CFLAGS+=-D“KBUILD\u STR(s)=\\s“-D”KBUILD\u BASENAME=KBUILD\u STR(您好)”
CFLAGS+=-D_uuu内核uuu-DMODULE-I$(内核构建目录)/include
内核构建目录=/lib/modules/2.6.18-194.el5/BUILD
TARGETNAME=hello
BUILD\u ALT\u DIR=linux
#主要目标(请注意,库和驱动程序都是.ko文件)
#
全部:$(BUILD\u ALT\u DIR)/$(TARGETNAME).ko
$(BUILD\u ALT\u DIR)/(TARGETNAME).o:hello.o
@回显链接对象到可加载模块
@mkdir-p$(构建替换目录)
@echo$(CURDIR)/$@
@$(LD)-Map=$@.Map-r-o$@$^
@回显“LD_D[$@]”
$(BUILD\u ALT\u DIR)/$(TARGETNAME).ko:$(BUILD\u ALT\u DIR)/$(TARGETNAME).o
@rm-f$(构建替换目录)/$(目标名称).o
@echo创建Makefile
@$(SHELL)-c'echo“obj-m:=$(TARGETNAME).o“>$(BUILD\u ALT\u DIR)/Makefile”
@$(SHELL)-c'echo“$(TARGETNAME)-objs:=$(TARGETNAME).o”>$(BUILD\u ALT\u DIR)/Makefile'
@$(SHELL)-c'echo.PHONY:'pwd`/$(BUILD\u ALT\u DIR)/$(TARGETNAME.o“>>$(BUILD\u ALT\u DIR)/Makefile'
@$(SHELL)-c'cd$(BUILD\u ALT\u DIR);$(MAKE)-c$(KERNEL\u BUILD\u DIR)M=`pwd`'
@回声“kou_D[$@]”
$(构建/替换/目录)/%.o:%.c
@echo将C源代码编译为目标文件:
@mkdir-p$(构建替换目录)
#@echo$(CURDIR)/$@
@$(CC)-c-墙$(CFLAGS)$(CFLAGS)$<-o$@
@回显“CC_D[$@]”
清洁:
rm-f$(BUILD\u ALT\u DIR)/*.o$(BUILD\u ALT\u DIR)/*.d$(BUILD\u ALT\u DIR)/core$(BUILD\u ALT\u DIR)/*.map
你好,c
#包括//这是必需的
#包括
#包括
静态int hello_init(void)
{ 
printk(KERN_警报“你好,世界”\n);
返回0;
}
静态void hello_退出(void)
{
printk(KERN_ALERT“再见,残酷的世界”);
}
模块_init(hello_init);
模块退出(你好退出);
第二次迭代:

好的,您已经确认了Make builds
\u helloworld.o
$(BUILD\u ALT\u DIR)/Makefile
。现在您可以发布
$(KERNEL\u BUILD\u DIR)
(在x86\u 64上)中的Makefile了吗

(我会冒险提出,i386上的
$(BUILD\u ALT\u DIR)
$(KERNEL\u BUILD\u DIR)
可能是相同的,但在x84\u 64上是不同的。)

编辑:(第三次迭代)
1400行?大部分在一个分支中?半打
包括
指令?特定于体系结构的分支?Autoconf

你被允许在适当的地方修改这个噩梦,还是你必须修补更高级别的工具,比如automake?(我这样问是因为在后一种情况下,找出问题所在并没有多大好处,你可能必须从头开始。)

1) 从$(KERNEL\u BUILD\u DIR)中,尝试
make M=$(BUILD\u ALT\u DIR)
(无论
$(BUILD\u ALT\u DIR)
是什么)。验证是否会显示相同的错误消息。如果没有,那么忽略接下来的内容(在这个迭代中)

2) 从
$(BUILD\u ALT\u DIR)
,尝试
make
,看看是否会出现相同的错误。如果确实如此,请尝试将makefile(在
$(BUILD\u ALT\u DIR)
中)替换为一个普通的makefile,如

#include <linux/autoconf.h> // this is needed

#include <linux/init.h>
#include <linux/module.h> 

static int hello_init(void)
{ 
  printk(KERN_ALERT "Hello, world\n");

    return 0;
}

static void hello_exit(void)
{
    printk(KERN_ALERT "Goodbye, cruel world\n");
}

module_init(hello_init);
module_exit(hello_exit);
并进行测试,然后重试步骤1。如果它只是说“琐碎的makefile正在工作”,并且没有给出错误,那么事情看起来不错

编辑:(第四次迭代)

好的,我们不能更改
$(内核构建目录)/Makefile
。这并不一定会让我们失望

您的建议(1)不起作用,因为$(BUILD\u ALT\u DIR)是一个输出目录,其中没有任何源

Make不需要源代码,无论这是否可行(无论“工作”的意思是什么),它都是您的makefile所尝试的:

all:
    @echo trivial makefile working
试试看会发生什么

“是否存在x86_64不支持内核模块的传统格式(CC)的可能性?”


我不完全确定您的意思,但我们可能可以通过实验来回答您的问题。

dmesg的输出告诉您出了什么问题:

@$(SHELL) -c 'cd $(BUILD_ALT_DIR); $(MAKE) -C $(KERNEL_BUILD_DIR) M=`pwd`'
在x86-64体系结构上,内核中运行的所有代码(包括模块)都必须使用特殊标志进行编译,该标志告诉编译器生成将在虚拟地址空间的上半部分运行的代码(用户模式程序在地址空间的下半部分运行)

如果我正确地读取了Makefile,那么您是在内核构建系统之外编译C代码,并且只为最终链接调用内核构建系统不要这样做。这不仅仅是内存模型,在编译C源代码时还必须添加其他几个标志。这些标志可以随着内核版本的变化而变化,甚至随着内核配置的变化而变化——您不知道,也不应该知道,因为内核构建系统会为您处理所有这些

它不仅仅是
-mcmodel=kernel
。还有很多其他问题,如果把它们弄错了,可能也会导致问题

您缺少正确的标志这一事实在代码中非常明显:

'hello' likely not compiled with -mcmodel=kernel
这个标志告诉C编译器总是隐式地包含
linux/autoconf.h
头。因为它总是隐式包含的,所以您永远不必手动包含它。而且,由于您从未手动包含它,因此它的位置允许更改—它将移动到
生成的/autoconf.h
,然后再移动到
linux/kconfig.h
,谁知道下一步它将在哪里结束


事实上,它在32位x86中完全适用于您,这只是运气。即使是在32位上,您也应该以正确的方式执行此操作。

要研究什么?除了风格元素之外?好的,你可以向我们展示有问题的makefile规则。谢谢你的回复,makefile有点长,我在问题中添加了它的摘录。这个makefile需要几次迭代。我认为你在试图建立“地狱世界”;你能证实吗
@$(SHELL) -c 'cd $(BUILD_ALT_DIR); $(MAKE) -C $(KERNEL_BUILD_DIR) M=`pwd`'
'hello' likely not compiled with -mcmodel=kernel
#include <linux/autoconf.h> // this is needed
-include include/linux/autoconf.h