Linux 设备驱动程序:符号“memcpy”未找到

发布于 2024-10-09 17:21:43 字数 2102 浏览 8 评论 0原文

我正在尝试编写一个Linux 设备驱动程序。我让它工作得很好,直到我尝试使用“memcpy”。我什至没有收到编译器错误,当我“make”时,它只是警告我:

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

I'm trying to write a Linux device driver. I've got it to work really well, until I tried to use "memcpy". I don't even get a compiler error, when I "make" it just warns me:

WARNING: "memcpy" [/root/homedir/sv/main.ko] undefined!

OK and when I try to load via insmod, I get on the console:

insmod: error inserting './main.ko': -1 Unknown symbol in module

and on dmesg:

main: Unknown symbol memcpy (err 0)

I include the following:

#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 */

The function using 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;
 }

Could someone help me? I thought the thing was in linux/string.h, but I get the error just the same. I'm using kernel 2.6.37-rc1 (I'm doing in in user-mode-linux, which works only since 2.6.37-rc1). Any help is greatly appreciated.

# 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

梦途 2024-10-16 17:21:43

我是在用户模式linux下进行的

您可以尝试不使用用户模式 ​​Linux 吗?

内核不与 libc 链接,但 UML 是一个例外。
这可以解释您的链接错误。

I'm doing it in user-mode-linux

Could you try without User-mode Linux?

The kernel does not link with the libc but UML is an exception.
That could explain your linking error.

£冰雨忧蓝° 2024-10-16 17:21:43

memcpy 要么定义为特定于架构(如果__HAVE_ARCH_MEMCPY),要么定义为lib/string.c中的通用版本。无论哪种情况,它都应该可用。查看/proc/kallsyms,使用objdump检查您的模块,并验证符号版本控制不会搞乱事情。

memcpy is either defined as arch specific (if __HAVE_ARCH_MEMCPY) or as a generic version in lib/string.c. In either case, it should be available. Look in /proc/kallsyms, check your module with objdump and also verify symbol versioning isn't messing things up.

独﹏钓一江月 2024-10-16 17:21:43

第一点是这是一个链接错误而不是编译错误。其实就是一个动态链接的问题。你的模块编译得很好,尽管有一个警告。只有当您加载它时才会失败。所以这与头文件无关。
第二点是 memcpy 在内核中被广泛定义和使用,因此没有理由找不到 memcpy 符号。

原因可能只是 GCC 本身的问题。 GCC 使用内置函数,其中一些函数可能引用内核中不存在的 libgcc。如果是这种情况,可以通过使用编译器选项 -fno-builtin 来解决

The first point is that this is a linking error and not a compile error. In fact it is a dynamic link problem. You module compiles fine albeit with a warning. It is only when you load it that this fails. So this has nothing to do with header files.
The second point is that memcpy is defined and used extensively in the kernel so the so there is no reason why the memcpy symbol is not being found.

The reason could simply be a problem with GCC itself. GCC uses builtin functions of which some may refer to libgcc which is not present in the kernel. If this is the case, this can be solved by using the compiler option -fno-builtin

月亮邮递员 2024-10-16 17:21:43

memcpy 在 string.h 中定义,您错过了包含它。

memcpy is defined in string.h which you missed to include.

才能让你更想念 2024-10-16 17:21:43

让我发表此评论作为答案,因为还有更多的空间可以写。

首先,“err 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 $@;

Let me post this comment as an answer, because there's more room to write.

First, "err 0" sound suspicious. (Because 0 is success.) Then, your Makefile has two KERNELDIR lines, the latter of which is ?=d, so it might not do what you want. There is also CFLAGS="-ARCH=um" which sounds so terribly wrong. -I$PWD is redundant. The KERNELRELASE check is not needed either. In total, it looks overly convoluted. Use this much simpler 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 $@;
寂寞陪衬 2024-10-16 17:21:43

包含正确的 string.h 标头;

#include <linux/string.h>

如果您遇到编译错误,请改为发布该错误。

Include the right string.hheader;

#include <linux/string.h>

If you have a compile error with this, post that instead.

坦然微笑 2024-10-16 17:21:43

该问题可能与 EXTRA_CFLAGS 声明有关。尝试删除包含的额外空间和架构的 -ie

EXTRA_CFLAGS+=-I$(PWD) ARCH=um

The issue might be with the EXTRA_CFLAGS declaration. Try removing the extra space for the include and the - for the architecture, i.e. :

EXTRA_CFLAGS+=-I$(PWD) ARCH=um
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文