Eu li bastante sobre como compilar um módulo de kernel no (e para) o Raspberry Pi, mas ainda não sou capaz de descobrir por que ele não está funcionando. Consegui construir o módulo, mas ele relata Invalid module format
quando tento insmod
o resultado. Aqui está o processo que segui. Primeiro, como root /root
, executei o seguinte 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
As primeiras linhas são de http://lostindetails.com/blog/post/Compiling-a-kernel-module-for-the-raspberry-pi-2
O resto eu escrevi para automatizar mais o processo. Depois que tudo isso for executado com êxito, eu tenho a fonte que deve corresponder exatamente ao kernel em execução, a configuração a ser correspondida e um link simbólico. Houve alguns redirecionamentos do local da web do github (aparentemente agora é https://raw.githubusercontent.com/ ), mas não há erros reais.
Então eu me torno o pi
usuário padrão e, em um diretório chamado /home/pi/projects/lkm
, tenho esse código-fonte para um módulo de brinquedo muito simples:
hello.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, eu construo o módulo com 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
Por fim, tento carregar o módulo:
sudo insmod hello.ko
O resultado, no entanto, é decepcionante:
insmod: ERRO: não foi possível inserir o módulo hello.ko: formato de módulo inválido
Detalhes possivelmente relevantes
Estou usando a jessie
versão mais recente do Raspbian em um 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)
Infelizmente, não tenho certeza de como solucionar mais esse problema ou corrigi-lo. Alguma pista?
Respostas:
Primeiro de tudo, certifique-se de usar os cabeçalhos de kernel adequados. Presumo que os cabeçalhos e o código fonte do kernel sejam mais atualizados que o kernel que você está executando.
Tente fazer uma
apt-get update && apt-get upgrade
reinstalação do módulo. Se o problema persistir, verifique três vezes se os cabeçalhos do kernel correspondem ao kernel atual, recompile novamente e tente instalar.Nota: estou usando Jessie.
UPDATE: Execute-os como root.
Pode ser necessário reiniciar. Depois disso, continue com os comandos abaixo, ainda usando a conta root.
Se
rpi-source
gerar um erro do GCC (algo sobre uma incompatibilidade de versão), tudo bem desde que sua versão atual do GCC seja superior . Executar emrpi-source --skip-gcc
vez derpi-source
Em seguida, continue com o seu exemplo Hello World. Crie a pasta e
cd
nela. Em seguida, crie os arquivos.Arquivos:
hello.c
Makefile ( diferencia maiúsculas de minúsculas?)
Agora que você possui seus arquivos, pode prosseguir e executar os comandos de construção habituais do Hello World:
Agora você deve verificar
dmesg
. A última linha deve ser impressaHello World :)
destacada em vermelho.Se sim, parabéns. Você acabou de criar e instalar um módulo do kernel.
Agora remova-o usando
rmmod hello
.dmesg
agora deve imprimirGoodbye World!
destacado em vermelho.Fontes: 1 2 3
fonte
rpi-source
peça seja suficiente. Você pode tentar construir o seu a partir desse ponto.Existe uma versão muito mais simples aqui, testada em jessie e stretch .
sudo apt-get install raspberrypi-kernel-headers
e quando seus arquivos estiverem no lugar:
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
Exemplo
Crie o
hello
diretório, entre e crie os seguintes arquivos:hello.c
eMakefile
.Eu recomendo trabalhar como usuário normal, não como root , apenas
insmod
,rmmod
e osmake modules_install
comandos requerem permissões de root, e o necessáriosudo
é mostrado nos seguintes comandos.hello.c (inalterado, seu arquivo)
Makefile (alterado)
Uso
make
(no mesmo diretório que o Makefile)sudo insmod hello.ko
Hello World :)
na saída dedmesg
sudo rmmod hello
Goodbye, world.
int a saída dedmesg
sudo make modules_install
instalará o módulo onde ele pertence, assimmodprobe
funcionará.fonte
rpi-update
,rpi-update
foi sugerido no de pandalion98 respostaapt
repositório do Raspbian , se não me engano. Atualizar o kernel significava executar orpi-update
script do Hexxeh . Hoje em dia, atualizarraspberrypi-kernel
ou executarrpi-update
praticamente a mesma coisa.raspberrypi-kernel-headers
, geralmente instala cabeçalhos de kernel incompatíveis, por experiência (os cabeçalhos tendem a ser uma versão mais nova que o kernel), por isso optei por "ir para o manual".no
getKernel.sh
arquivo addantes
(agora na imagem padrão rpi /proc/config.gz não existe)
fonte