He leído bastante sobre cómo compilar un módulo de kernel en (y para) la Raspberry Pi, pero todavía no puedo entender por qué no funciona. He podido construir el módulo, pero informa Invalid module format
cuando intento insmod
el resultado. Aquí está el proceso que seguí. Primero, como root debajo /root
ejecuté el siguiente script de shell:
getKernel.sh
#! /usr/bin/bash
FIRMWARE_HASH=$(zgrep "* firmware as of" /usr/share/doc/raspberrypi-bootloader/changelog.Debian.gz | head -1 | awk '{ print $5 }')
KERNEL_HASH=$(wget https://raw.githubusercontent.com/raspberrypi/firmware/$FIRMWARE_HASH/extra/git_hash -O -)
git clone https://github.com/raspberrypi/linux
cd linux
git checkout $KERNEL_HASH
wget https://raw.githubusercontent.com/raspberrypi/firmware/$FIRMWARE_HASH/extra/Module.symvers
zcat /proc/config.gz >.config
make oldconfig
make modules_prepare
ln -s /root/linux /lib/modules/$(uname -r)/build
Las primeras líneas son de http://lostindetails.com/blog/post/Compiling-a-kernel-module-for-the-raspberry-pi-2
El resto lo escribí para automatizar más el proceso. Una vez que todo se ejecuta correctamente, tengo la fuente que debe coincidir exactamente con el núcleo en ejecución, la configuración para que coincida y un enlace simbólico. Hubo algunos redireccionamientos desde la ubicación web de github (aparentemente ahora es https://raw.githubusercontent.com/ ) pero no hay errores reales.
Luego me convierto en el pi
usuario predeterminado y en un directorio llamado /home/pi/projects/lkm
Tengo este código fuente para un módulo de juguete muy simple:
Hola C
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Do-nothing test driver");
MODULE_VERSION("0.1");
static int __init hello_init(void){
printk(KERN_INFO "Hello, world.\n");
return 0;
}
static void __exit hello_exit(void){
printk(KERN_INFO "Goodbye, world.\n");
}
module_init(hello_init);
module_exit(hello_exit);
Finalmente, construyo el módulo con este Makefile
Makefile
MODSRC=/home/pi/projects/lkm
obj-m+=hello.o
all:
make -C /lib/modules/$(shell uname -r)/build M=${MODSRC} modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=${MODSRC} clean
Finalmente, intento cargar el módulo:
sudo insmod hello.ko
El resultado, sin embargo, es decepcionante:
insmod: ERROR: no se pudo insertar el módulo hello.ko: formato de módulo no válido
Posiblemente detalles relevantes
Estoy usando la última jessie
versión actual de Raspbian en una Raspberry Pi2.
$ uname --kernel-release --kernel-version
4.1.13-v7+ #826 SMP PREEMPT Fri Nov 13 20:19:03 GMT 2015
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/4.9/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Raspbian 4.9.2-10' --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libitm --disable-libquadmath --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.9-armhf/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.9-armhf --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.9-armhf --with-arch-directory=arm --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-sjlj-exceptions --with-arch=armv6 --with-fpu=vfp --with-float=hard --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
Thread model: posix
gcc version 4.9.2 (Raspbian 4.9.2-10)
Desafortunadamente, no estoy seguro de cómo solucionar este problema o solucionarlo. ¿Alguna pista?
Respuestas:
En primer lugar, asegúrese de usar los encabezados de kernel adecuados. Supongo que los encabezados del núcleo y el código fuente están más actualizados que el núcleo que está ejecutando.
Intente hacer y
apt-get update && apt-get upgrade
luego reinstale el módulo. Si el problema persiste, verifique tres veces que los encabezados de su kernel coincidan con su kernel actual, vuelva a compilar e intente instalar.Nota: estoy usando Jessie.
ACTUALIZACIÓN: Ejecútelos como root.
Es posible que deba reiniciar. Después de eso, continúe con los comandos a continuación, aún utilizando la cuenta raíz.
Si
rpi-source
arroja un error de GCC (algo acerca de una discrepancia de versión), está bien siempre que su versión actual de GCC sea más alta . Correr enrpi-source --skip-gcc
lugar derpi-source
Luego, continúe con su ejemplo de Hello World. Crea la carpeta y
cd
en ella. Luego, crea los archivos.Archivos:
Hola C
Makefile (¿ distingue entre mayúsculas y minúsculas?)
Ahora que tiene sus archivos, puede continuar y ejecutar los comandos de compilación habituales de Hello World:
Ahora deberías comprobarlo
dmesg
. La última línea debe imprimirseHello World :)
resaltada en rojo.Si lo haces, felicidades. Acaba de crear e instalar un módulo de kernel.
Ahora quítelo usando
rmmod hello
.dmesg
ahora debería imprimirseGoodbye World!
resaltado en rojo.Fuentes: 1 2 3
fuente
rpi-source
parte sea suficiente. Puedes intentar construir el tuyo desde ese punto.Aquí hay una versión mucho más simple, probada en jessie y stretch .
sudo apt-get install raspberrypi-kernel-headers
y luego cuando sus archivos estén en su lugar:
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
Ejemplo
Crea el
hello
directorio, entra y crea los siguientes archivos:hello.c
yMakefile
.Yo recomiendo trabajando como usuario normal, no tiene raíz , solamente
insmod
,rmmod
ymake modules_install
los comandos requieren permisos de root, y lo necesariosudo
se muestra en los siguientes comandos.hello.c (sin cambios, su archivo)
Makefile (modificado)
Uso
make
(en el mismo directorio que el Makefile)sudo insmod hello.ko
Hello World :)
en la salida dedmesg
sudo rmmod hello
Goodbye, world.
int la salida dedmesg
sudo make modules_install
instalará el módulo donde pertenece, pormodprobe
lo que funcionará.fuente
rpi-update
,rpi-update
se sugirió en la respuesta de pandalion98apt
repositorio de Raspbian , si no me equivoco. Actualizar el núcleo significaba ejecutar elrpi-update
script de Hexxeh . En estos días, la actualizaciónraspberrypi-kernel
o la ejecuciónrpi-update
hacen más o menos lo mismo.raspberrypi-kernel-headers
, generalmente instala encabezados de kernel no coincidentes, por experiencia (los encabezados tienden a ser una versión más nueva que el kernel), de ahí por qué opté por "ir a manual".en el
getKernel.sh
archivo agregarantes de
(ahora en la imagen rpi predeterminada /proc/config.gz no existe)
fuente