Драйвер устройства Linux: символ "memcpy" не найден - PullRequest
6 голосов
/ 31 декабря 2010

Я пытаюсь написать драйвер устройства 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 (я работаю в user-mode-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

Ответы [ 7 ]

2 голосов
/ 04 января 2011

Я делаю это в user-mode-linux

Не могли бы вы попробовать без пользовательского режима Linux?

Ядро не связывается с libc, но UML является исключением. Это может объяснить вашу ошибку компоновки.

1 голос
/ 31 декабря 2010

Во-первых, это ошибка компоновки, а не ошибка компиляции.На самом деле это проблема динамического соединения.Ваш модуль прекрасно компилируется, хотя и с предупреждением.Только когда вы загрузите его, это не удастся.Так что это не имеет ничего общего с заголовочными файлами.Второй момент заключается в том, что memcpy определен и широко используется в ядре, поэтому нет причины, по которой символ memcpy не был найден.

Причиной может быть просто проблема с самим GCC.GCC использует встроенные функции, некоторые из которых могут ссылаться на libgcc, которого нет в ядре.Если это так, это можно решить с помощью опции компилятора -fno-builtin

1 голос
/ 31 декабря 2010

memcpy определяется как специфичная для арки (если __HAVE_ARCH_MEMCPY) или как универсальная версия в lib / string.c . В любом случае, это должно быть доступно. Загляните в / proc / kallsyms , проверьте ваш модуль с помощью objdump , а также убедитесь, что управление версиями символов не портит.

0 голосов
/ 04 января 2011

Возможно, проблема связана с объявлением EXTRA_CFLAGS.Попробуйте удалить дополнительное место для включаемого файла и - для архитектуры: , т.е. :

EXTRA_CFLAGS+=-I$(PWD) ARCH=um
0 голосов
/ 31 декабря 2010

Включите правильный заголовок string.h;

#include <linux/string.h>

Если у вас есть ошибка компиляции, опубликуйте это вместо этого.

0 голосов
/ 31 декабря 2010

Позвольте мне опубликовать этот комментарий в качестве ответа, потому что есть больше места для записи.

Во-первых, "err 0" звучит подозрительно. (Потому что 0 - это успех.) Затем ваш Makefile имеет две строки KERNELDIR, последняя из которых? Есть также CFLAGS = "- ARCH = um", который звучит так ужасно неправильно. -Я $ 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 $@;
0 голосов
/ 31 декабря 2010

memcpy определен в string.h, который вы пропустили, чтобы включить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...