我试图在Ubuntu 16.04 LTS中编译内核版本4.4。我添加或修改了一些代码,将块I / O层中写入块的块号存储到自定义缓冲区中。
我修改了代码[linux-kernel-location] /block/blk-core.c (original):
...
#include <custom/custom-buffer.h>
...
blk_qt_t submit_bio(int rw, struct bio *bio)
{
...
if(rw & WRITE)
{
unsigned long cntUnit = bio->bi_bdev->bd_super->s_blocks / bdev_logical_block_size(bio->bi_bdev);
unsigned long blk_no = bio->bi_iter.bi_sector / cntUnit;
count_vm_events(PGPGOUT, count);
custom_buf_write_blk_no(blk_no);
}
...
}
...
[linux-kernel-location] / block / Makefile (original):
...
obj-y += custom/
[linux-kernel-location] / block / Kconfig (original):
...
source "block/custom/Kconfig"
并创建目录[linux-kernel-location] / include / custom,[linux-kernel-location] / block / custom。然后,我创建了文件[linux-kernel-location] /include/custom/custom-buffer.h:
#ifndef _CUSTOM_BUFFER_H_
#define _CUSTOM_BUFFER_H_
extern int custom_buf_write_blk_no(unsigned long blk_no);
#endif
[Linux内核-位置] /块/自定义/生成文件:
obj-y += custom-buffer.o
[Linux内核-位置] /块/定制/的Kconfig:
config CUSTOM_BUFFER
tristate
depends on BLOCK
default y
[linux-kernel-location] /block/custom/custom-buffer.c(包括custom_buf_write_blk_no(unsigned long blk_no)
与EXPORT_SYMBOL
宏的定义)。
我在linux内核位置的shell中输入了make
命令,并获得了以下结果:
...
LD init/built-in.o
block/built-in.o: In function `submit_bio':
[linux-kernel-location]/block/blk-core.c:2117: undefined reference to `custom_buf_write_blk_no'
block/built-in.o:(___ksymtab+custom_buf_write_blk_no+0x0): undefined reference to `custom_buf_write_blk_no'
Makefile:927: recipe for target 'vmlinux' failed
make: *** [vmlinux] Error 1
我的猜测是我需要修复Makefile,我该如何修复它?
编辑:我也知道这种情况正在发生,因为链接器无法在链接过程中找到符号。但我不知道如何在Kbuild系统适用的Makefile中修复它。
自我解决:custom-buffer.c
信函错误。我正确地修复它以便编译好。
找到拼写错误太难了......
答案 0 :(得分:1)
是的,很难找到拼写错误。但编译器试图向我们展示打字错误的位置。
我试图重现您的问题,以撰写可能有助于其他人访问此问题的答案。
首先,如果您在文件名中输入错误会发生什么?让我们说custom/custom-buffe.c
内核构建系统会抱怨:
CHK include/generated/compile.h
make[2]: *** No rule to make target 'block/custom/custom-buffer.o', needed by 'block/custom/built-in.o'. Stop.
scripts/Makefile.build:403: recipe for target 'block/custom' failed
make[1]: *** [block/custom] Error 2
Makefile:943: recipe for target 'block' failed
make: *** [block] Error 2
因此,显然构建规则正在寻找创建custom-buffer.o
的文件,但它缺失了。默认情况下,它应该有custom-buffer.c
。
来自documentation:
最简单的kbuild makefile包含一行:
实施例: obj-y + = foo.o
这告诉kbuild该目录中有一个名为的对象 foo.o. foo.o将从foo.c或foo.S。
构建
不是你的情况。那么我在函数定义中做了一个拼写错误(buff
vs buf
):
int custom_buff_write_blk_no(unsigned long blk_no) {
printk(KERN_INFO "WIP NUMBER %lu\n", blk_no);
return 0;
}
EXPORT_SYMBOL(custom_buff_write_blk_no);
现在,在构建之后,我有来自编译器的信息:
LD init/built-in.o
block/built-in.o: In function `submit_bio':
(.text+0x8bb0): undefined reference to `custom_buf_write_blk_no'
Makefile:929: recipe for target 'vmlinux' failed
make: *** [vmlinux] Error 1
我们可以通过发布make V=1
+ ld -m elf_x86_64 --build-id -o .tmp_vmlinux1 -T ./arch/x86/kernel/vmlinux.lds arch/x86/kernel/head_64.o arch/x86/kernel/head64.o arch/x86/kernel/head.o init/built-in.o --start-gr
oup usr/built-in.o arch/x86/built-in.o kernel/built-in.o certs/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o block/built-in.o lib/lib.
a arch/x86/lib/lib.a lib/built-in.o arch/x86/lib/built-in.o drivers/built-in.o sound/built-in.o firmware/built-in.o arch/x86/pci/built-in.o arch/x86/power/built-in.o arch/x86/video
/built-in.o arch/x86/ras/built-in.o net/built-in.o virt/built-in.o --end-group
block/built-in.o: In function `submit_bio':
(.text+0x8bb0): undefined reference to `custom_buf_write_blk_no'
首先,我们认为一切都是正确的,我们的custom_buf_write_blk_no
符号应该在文件block/custom/build-in.o
中。这里我们没有看到这个文件。但是,Kbuild系统递归地将所有对象合并到一个build-in.o:
Kbuild编译所有$(obj-y)文件。然后它打电话 “$(LD)-r”将这些文件合并到一个内置的.o文件中。 build-in.o稍后由父Makefile链接到vmlinux。
所以应该在block/build-in.o
。为了确保我们可以通过调查make V=1
输出来跟踪它:
...
ld -m elf_x86_64 -r -o block/custom/built-in.o block/custom/custom-buffer.o
...
ld -m elf_x86_64 -r -o block/built-in.o block/bio.o block/elevator.o block/blk-core.o block/blk-tag.o block/blk-sysfs.o block/blk-flush.o block/blk-settings.o block/blk-ioc.o
block/blk-map.o block/blk-exec.o block/blk-merge.o block/blk-softirq.o block/blk-timeout.o block/blk-iopoll.o block/blk-lib.o block/blk-mq.o block/blk-mq-tag.o block/blk-mq-sysfs.o
block/blk-mq-cpu.o block/blk-mq-cpumap.o block/ioctl.o block/genhd.o block/scsi_ioctl.o block/partition-generic.o block/ioprio.o block/partitions/built-in.o block/bounce.o block/b
sg.o block/noop-iosched.o block/deadline-iosched.o block/cfq-iosched.o block/compat_ioctl.o block/custom/built-in.o
确实,我们有custom-buffer.o
。那么为什么我们有未定义的参考?好吧,我们可以使用block/build-in.o
:
objdump -t block/built-in.o | grep custom
中的符号
0000000000000000 l d ___ksymtab+custom_buff_write_blk_no 0000000000000000 ___ksymtab+custom_buff_write_blk_no
0000000000000000 l df *ABS* 0000000000000000 custom-buffer.c
000000000000132e l O __ksymtab_strings 0000000000000019 __kstrtab_custom_buff_write_blk_no
0000000000000000 *UND* 0000000000000000 custom_buf_write_blk_no
0000000000000000 g O ___ksymtab+custom_buff_write_blk_no 0000000000000010 __ksymtab_custom_buff_write_blk_no
0000000000025ed0 g F .text 0000000000000017 custom_buff_write_blk_no
现在我们看到符号custom_buff_write_blk_no
,编译器抱怨他正在寻找custom_buf_write_blk_no
。