2010-12-31 20 views
6

Estoy intentando escribir un controlador de dispositivo Linux. Tengo que funcionar muy bien, hasta que intenté usar "memcpy". Ni siquiera consigo un error del compilador, cuando "hacen" simplemente me advierte:Controlador de dispositivo Linux: no se encuentra el símbolo "memcpy"

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

OK y cuando intento cargar con insmod, me sale en la consola:

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

y en dmesg:

main: Unknown symbol memcpy (err 0)

I incluyen los siguientes:

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

La función utilizando 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; 
} 

Podría alguien ayudarme? Pensé que estaba en linux/string.h, pero me sale el error. Estoy usando kernel 2.6.37-rc1 (lo estoy haciendo en user-mode-linux, que funciona solo desde 2.6.37-rc1). Cualquier ayuda es muy apreciada.

# 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 
+1

Creo que te falta '#include ' ... obviamente, a menos que uno de los encabezados de linux ya lo incluya: p – Machinarius

+4

@Drknezz no es así y eso se debe a que no puedes usarlo. El kernel no es un entorno alojado y no hay stdio. Y el código no incluye stdio, por lo que tampoco hay * razón * para incluirlo. – hobbs

+0

@Hinton es un error de enlace, no un error de compilación. ¿Cómo estás construyendo tu módulo? – hobbs

Respuesta

2

lo estoy haciendo en modo de usuario en Linux

Podría tratar sin Usuario -mode Linux?

El núcleo no se vincula con la libc pero UML es una excepción. Eso podría explicar su error de enlace.

+0

Sí, definitivamente tenías razón sobre el UML, pero: El problema se resolvió hoy (sin mi ayuda). Parece que Memcpy funciona ... La única razón que veo para esto es que: Este es un proyecto universitario, y Lead compila el UML para nosotros. Estoy bastante seguro de que estropearon algo hace algunos días y lo arreglaron ahora; gracias por la respuesta. Lo único que puedo recomendar ahora es compilar UML y hacerlo correctamente. – Hinton

0

memcpy se define en string.h que no incluyó.

+1

En el kernel, no puedo simplemente incluir string.h; Lo intenté con linux/string.h que puede usarse en el kernel, pero eso no funcionó ... Debería haber obtenido un error/advertencia de compilación de todos modos en lugar de este error de sistema de compilación si algo andaba mal con el incluye – Hinton

0

Déjame publicar este comentario como respuesta, porque hay más espacio para escribir.

Primero, "err 0" sonido sospechoso. (Porque 0 es éxito). Entonces, tu archivo Makefile tiene dos líneas KERNELDIR, la última de las cuales es? = D, por lo que es posible que no haga lo que deseas. También hay CFLAGS = "- ARCH = um" que suena terriblemente mal. -I $ PWD es redundante. La verificación KERNELRELASE tampoco es necesaria. En total, se ve excesivamente intrincado. Utilice esta MF mucho más simple:

 
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 [email protected]; 
+0

Cuando pruebo esto, siempre obtengo "nada por hacer para todos/limpiar/etc." Tengo mi archivo makefile principalmente de LDD3. – Hinton

+0

¿Estás seguro de que tienes las pestañas correctas? (De lo contrario, consulte '.PHONY: todos los módulos limpian') – user502515

1

memcpy está bien definido como arco de concreto (si __HAVE_ARCH_MEMCPY) o como una versión genérica en lib/string.c. En cualquier caso, debería estar disponible. Mire en /proc/kallsyms, revise su módulo con objdump y también verifique que el control de versiones de los símbolos no lo esté arruinando.

0

Incluya el encabezado string.h correcto;

#include <linux/string.h> 

Si tiene un error de compilación con esto, publíquelo en su lugar.

+1

El error no es un error del compilador, es un error del enlazador. – doron

+0

Sí, porque no incluye el encabezado correcto, Hinton afirma 'linux/string.h' da un error de compilación y lo estoy pidiendo. – ismail

1

El primer punto es que se trata de un error de enlace y no de compilación. De hecho, es un problema de enlace dinámico. Tu módulo compila bien aunque con una advertencia. Solo cuando lo cargas, esto falla. Entonces esto no tiene nada que ver con los archivos de encabezado. El segundo punto es que memcpy se define y usa extensivamente en el kernel, por lo que no hay ninguna razón por la cual no se encuentre el símbolo memcpy.

La razón podría ser simplemente un problema con GCC. GCC usa funciones integradas de las cuales algunas pueden referirse a libgcc que no está presente en el kernel.Si este es el caso, esto puede resolverse utilizando la opción del compilador -fno-builtin

+0

Si se necesitaban opciones, ya se habrían agregado en los archivos make del kernel. Hablando de eso, algunos archivos make ya agregan '-fno-builtin-memcpy' a veces. – user502515

0

El problema podría ser con la declaración EXTRA_CFLAGS. Prueba a eliminar el espacio adicional para la inclusión y la - para la arquitectura, es decir :

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