Przeczytałem sporo o tym, jak skompilować moduł jądra na (i dla) Raspberry Pi, ale wciąż nie jestem w stanie zrozumieć, dlaczego to nie działa. Byłem w stanie zbudować moduł, ale raportuje, Invalid module format
gdy próbuję uzyskać insmod
wynik. Oto proces, który zastosowałem. Najpierw jako root w ramach /root
I wykonałem następujący skrypt powłoki:
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
Pierwsze kilka wierszy pochodzi z http://lostindetails.com/blog/post/Compiling-a-kernel-module-for-the-raspberry-pi-2
Resztę napisałem, aby zautomatyzować większą część procesu. Gdy wszystko zakończy się powodzeniem, mam źródło, które powinno dokładnie pasować do działającego jądra, konfiguracji do dopasowania i dowiązania symbolicznego. Były pewne przekierowania z lokalizacji internetowej github (najwyraźniej jest to teraz https://raw.githubusercontent.com/ ), ale nie ma rzeczywistych błędów.
Następnie zostaję domyślnym pi
użytkownikiem i w katalogu o nazwie /home/pi/projects/lkm
mam ten kod źródłowy dla bardzo prostego modułu zabawki:
cześć, 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);
Na koniec buduję moduł z tym 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
Wreszcie próbuję załadować moduł:
sudo insmod hello.ko
Wynik jest jednak rozczarowujący:
insmod: ERROR: nie można wstawić modułu hello.ko: nieprawidłowy format modułu
Ewentualnie istotne szczegóły
Korzystam z najnowszej jessie
wersji Raspbian na 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)
Niestety nie jestem pewien, jak rozwiązać ten problem lub go naprawić. Jakieś wskazówki?
Odpowiedzi:
Przede wszystkim upewnij się, że używasz odpowiednich nagłówków jądra. Zakładam, że nagłówki jądra i kod źródłowy są bardziej aktualne niż jądro, z którego korzystasz.
Spróbuj wykonać, a
apt-get update && apt-get upgrade
następnie ponownie zainstaluj moduł. Jeśli problem nadal występuje, potrójnie sprawdź, czy nagłówki jądra są zgodne z bieżącym jądrem, ponownie skompiluj ponownie, a następnie spróbuj zainstalować.Uwaga: używam Jessie.
AKTUALIZACJA: Uruchom je jako root.
Może być konieczne ponowne uruchomienie komputera. Następnie wykonaj poniższe polecenia, nadal korzystając z konta root.
Jeśli
rpi-source
zgłasza błąd GCC (coś o niedopasowaniu wersji), jest w porządku, o ile aktualna wersja GCC jest wyższa . Uruchomrpi-source --skip-gcc
zamiastrpi-source
Następnie przejdź do przykładu Hello World. Utwórz folder i
cd
do niego. Następnie utwórz pliki.Pliki:
cześć, c
Makefile ( wielkość liter ma znaczenie?)
Teraz, gdy masz już swoje pliki, możesz śmiało uruchamiać zwykłe polecenia kompilacji Hello World:
Powinieneś teraz sprawdzić
dmesg
. Ostatni wiersz powinien byćHello World :)
podświetlony na czerwono.Jeśli to zrobisz, gratulacje. Właśnie stworzyłeś i zainstalowałeś moduł jądra.
Teraz usuń go za pomocą
rmmod hello
.dmesg
powinien teraz drukowaćGoodbye World!
podświetlony na czerwono.Źródła: 1 2 3
źródło
rpi-source
część będzie wystarczająca. Od tego momentu możesz spróbować zbudować swój.Jest tutaj o wiele prostsza wersja, przetestowana na jessie i stretch .
sudo apt-get install raspberrypi-kernel-headers
a następnie, gdy pliki są na miejscu:
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
Przykład
Utwórz
hello
katalog, wejdź do środka i utwórz następujące pliki:hello.c
iMakefile
.I zalecamy pracę jako zwykły użytkownik, a nie głównym , tylko
insmod
,rmmod
imake modules_install
polecenia wymagają uprawnień administratora, a koniecznesudo
jest pokazany w poniższych poleceń.hello.c (niezmieniony, twój plik)
Makefile (zmieniony)
Stosowanie
make
(w tym samym katalogu co plik Makefile)sudo insmod hello.ko
Hello World :)
w wynikachdmesg
sudo rmmod hello
Goodbye, world.
int wynikdmesg
sudo make modules_install
zainstaluje moduł tam, gdzie należy, więcmodprobe
będzie działać.źródło
rpi-update
,rpi-update
zasugerowano w odpowiedzi pandalion98apt
repozytorium Raspbian , jeśli się nie mylę. Aktualizacja jądra oznaczała uruchomienierpi-update
skryptu Hexxeh . Obecnie aktualizowanieraspberrypi-kernel
lub uruchamianierpi-update
robi prawie to samo.raspberrypi-kernel-headers
to, zwykle instaluje niedopasowane nagłówki jądra, z doświadczenia (nagłówki są zwykle nowszą wersją niż jądro), dlatego zdecydowałem się na „przejście ręcznie”.w
getKernel.sh
pliku dodajprzed
(teraz domyślnie obraz rpi /proc/config.gz nie istnieje)
źródło