我正在尝试编写Linux设备驱动程序。我已经让它工作得很好,直到我尝试使用“memcpy”。我甚至没有得到编译器错误,当我“制造”它只是警告我:
WARNING: "memcpy" [/root/homedir/sv/main.ko] undefined!
好的,当我尝试通过insmod加载时,我进入控制台:
insmod: error inserting './main.ko': -1 Unknown symbol in module
和dmesg:
main: Unknown symbol memcpy (err 0)
我包含以下内容:
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/cdev.h>
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_*_user */
使用memcpy的函数:
static int dc_copy_to_user(char __user *buf, size_t count, loff_t *f_pos,
struct sv_data_dev *dev)
{
char data[MAX_KEYLEN];
size_t i = 0;
/* Copy the bulk as long as there are 10 more bytes to copy */
while (i < (count + MAX_KEYLEN)) {
memcpy(data, &dev->data[*f_pos + i], MAX_KEYLEN);
ec_block(dev->key, data, MAX_KEYLEN);
if (copy_to_user(&buf[i], data, MAX_KEYLEN)) {
return -EFAULT;
}
i += MAX_KEYLEN;
}
return 0;
}
有人可以帮助我吗?我认为这件事是在linux / string.h中,但我得到的错误是一样的。我正在使用内核2.6.37-rc1(我在用户模式linux中进行,仅在2.6.37-rc1之后才有效)。任何帮助是极大的赞赏。
# Context dependent makefile that can be called directly and will invoke itself
# through the kernel module building system.
KERNELDIR=/usr/src/linux
ifneq ($(KERNELRELEASE),)
EXTRA_CFLAGS+=-I $(PWD) -ARCH=um
obj-m := main.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD = $(shell pwd)
all:
$(MAKE) V=1 ARCH=um -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf Module.symvers .*.cmd *.ko .*.o *.o *.mod.c .tmp_versions *.order
endif
答案 0 :(得分:2)
我在user-mode-linux
中这样做
你可以试试没有用户模式的Linux吗?
内核不与libc链接,但UML是一个例外。 这可以解释您的链接错误。
答案 1 :(得分:1)
memcpy
被定义为特定于arch(如果__HAVE_ARCH_MEMCPY
)或 lib / string.c 中的通用版本。在任何一种情况下,都应该可用。查看 / proc / kallsyms ,使用 objdump 检查模块,并验证符号版本控制是不是搞乱了。
答案 2 :(得分:1)
第一点是这是一个链接错误而不是编译错误。实际上这是一个动态链接问题。尽管有警告,你的模块编译得很好。只有当你加载它时才会失败。所以这与头文件无关。 第二点是memcpy在内核中被广泛定义和使用,所以没有理由没有找到memcpy符号。
原因可能只是GCC本身的一个问题。 GCC使用内置函数,其中一些函数可能引用内核中不存在的libgcc。如果是这种情况,可以使用编译器选项-fno-builtin
答案 3 :(得分:0)
memcpy在string.h中定义,你错过了它。
答案 4 :(得分:0)
让我发一下这个评论作为答案,因为还有更多的空间可以写。
首先,“错误0”听起来很可疑。 (因为0是成功的。)然后,你的Makefile有两个KERNELDIR行,后者是?= d,所以它可能不会做你想要的。还有CFLAGS =“ - ARCH = um”,听起来非常错误。 -I $ PWD是多余的。也不需要KERNELRELASE检查。总的来说,它看起来过于复杂。使用这个更简单的MF:
obj-m := main.o KERNELDIR = /lib/modules/$(shell uname -r)/build all: modules modules modules_install clean: ${MAKE} V=1 ARCH=um -C ${KERNELDIR} M=$$PWD $@;
答案 5 :(得分:0)
包含正确的string.h
标题;
#include <linux/string.h>
如果您对此有编译错误,请改为发布。
答案 6 :(得分:0)
问题可能出在EXTRA_CFLAGS
声明中。尝试删除包含的额外空间和体系结构的-
,即:
EXTRA_CFLAGS+=-I$(PWD) ARCH=um