2010-12-31 20 views
6

Sto provando a scrivere un driver di periferica Linux. Ho funzionato molto bene, fino a quando ho provato a usare "memcpy". Non ho nemmeno ottenere un errore di compilazione, quando mi "faccio" solo mi avverte:Driver di dispositivo Linux: simbolo "memcpy" non trovato

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

OK e quando provo a caricare tramite insmod, ottengo sulla console:

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

e dmesg:

main: Unknown symbol memcpy (err 0)

ho sono i seguenti:

#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 funzione usando 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; 
} 

qualcuno potrebbe aiutarmi? Ho pensato che la cosa fosse in linux/string.h, ma ottengo l'errore lo stesso. Sto usando il kernel 2.6.37-rc1 (sto facendo in user-mode-linux, che funziona solo dal 2.6.37-rc1). Qualsiasi aiuto è molto apprezzato.

# 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

Penso che manchi '#include ' ... ovviamente a meno che uno degli header di Linux non lo includa già: p – Machinarius

+4

@Drknezz non lo fa e questo perché non puoi usarlo. Il kernel non è un ambiente ospitato e non c'è stdio. E il codice non include stdio quindi non c'è anche * motivo * per includerlo. – hobbs

+0

@Hinton è un errore di collegamento, non un errore di compilazione. Come stai costruendo il tuo modulo? – hobbs

risposta

2

lo sto facendo in user-mode-linux

Potrebbe provare senza utente -Mode Linux?

Il kernel non si collega alla libc ma UML è un'eccezione. Questo potrebbe spiegare il tuo errore di collegamento.

+0

Sì, avevi sicuramente ragione riguardo a UML, ma: il problema si è risolto oggi (senza il mio aiuto). Memcpy sembra funzionare ... L'unica ragione per cui vedo questo è questo: questo è un progetto universitario, e Lead compila l'UML per noi. Sono abbastanza sicuro che hanno incasinato qualcosa qualche giorno fa e l'hanno risolto ora; Grazie per la risposta. L'unica cosa che posso raccomandare ora è compilare l'UML per te stesso e farlo correttamente. – Hinton

0

memcpy è definito in string.h che non è stato incluso.

+1

Nel kernel, non posso semplicemente includere string.h; L'ho provato con linux/string.h che potrebbe essere usato nel kernel, ma non ha funzionato ... Avrei dovuto comunque ottenere un errore/avviso del compilatore invece di questo errore di sistema build se qualcosa non andava con lo include – Hinton

0

Lasciatemi postare questo commento come risposta, perché c'è più spazio per scrivere.

In primo luogo, "err 0" è sospetto. (Perché 0 è successo.) Quindi il tuo Makefile ha due linee KERNELDIR, l'ultima delle quali è? = D, quindi potrebbe non fare quello che vuoi. C'è anche CFLAGS = "- ARCH = um" che suona così terribilmente sbagliato. -I $ PWD è ridondante. Neanche il controllo KERNELRELASE è necessario. In totale, sembra eccessivamente convoluto. Utilizzare questo molto più semplice 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 [email protected]; 
+0

Quando provo questo, ottengo sempre "niente da fare per tutti/clean/ecc." Ho il mio makefile principalmente da LDD3. – Hinton

+0

Sei sicuro di avere le schede giuste? (In caso contrario, vedere '.PHONY: tutti i moduli puliti') – user502515

1

memcpy è sia definito come arco specifica (se __HAVE_ARCH_MEMCPY) o come una versione generica in lib/string.c. In entrambi i casi, dovrebbe essere disponibile. Cerca in /proc/kallsyms, controlla il tuo modulo con objdump e verifica anche che il controllo delle versioni dei simboli non sia un problema.

0

Includere l'intestazione string.h corretta;

#include <linux/string.h> 

Se si dispone di un errore di compilazione con questo, post che invece.

+1

L'errore non è un errore del compilatore, è un errore del linker. – doron

+0

Sì, poiché non include l'intestazione giusta, Hinton afferma che 'linux/string.h' fornisce un errore di compilazione e lo chiedo. – ismail

1

Il primo punto è che si tratta di un errore di collegamento e non di un errore di compilazione. In effetti è un problema di collegamento dinamico. Il modulo si compila bene anche se con un avvertimento. È solo quando lo carichi che questo fallisce. Quindi questo non ha nulla a che fare con i file di intestazione. Il secondo punto è che la memcpy è definita e utilizzata estesamente nel kernel, quindi non c'è motivo per cui il simbolo memcpy non venga trovato.

La ragione potrebbe essere semplicemente un problema con GCC stesso. GCC usa funzioni incorporate di cui alcuni potrebbero fare riferimento a libgcc che non è presente nel kernel.Se questo è il caso, questo può essere risolto utilizzando l'opzione del compilatore -fno-builtin

+0

Se fossero necessarie delle opzioni, sarebbero già state aggiunte nei makefile del kernel. A proposito, alcuni makefile arch talvolta aggiungono '-fno-builtin-memcpy' a volte. – user502515

0

Il problema potrebbe essere con la dichiarazione EXTRA_CFLAGS. Provare a rimuovere lo spazio aggiuntivo per l'inclusione ed il - per l'architettura, cioè :

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