„Brak wersji symbolu dla module_layout” podczas próby załadowania usbhid.ko

27

Próbuję zbudować własny moduł usbhid.ko, ale po skompilowaniu nie mogę go załadować. dmesgmówi no symbol version for module_layout. Zastanawiam się, na czym polega problem? Użyłem już źródła jądra dostarczonego przez Ubuntu i upewniłem się, że wersja jądra jest taka sama.

SpecC
źródło

Odpowiedzi:

22

Problem polega na tym, że podczas budowania modułu w drzewie źródeł jądra prawdopodobnie brakowało pliku Modules.symvers. System Kbuild faktycznie ostrzega o tym podczas budowania modułu. Jeśli brakuje Modules.symvers, zobaczysz:

Ostrzeżenie: brak wersji zrzutu /usr/src/linux-2.6.34-12/Modules.symvers; moduły nie będą miały żadnych zależności ani wersji.

Jeśli twoje jądro zostało CONFIG_MODVERSIONSwłączone, to podczas fazy modpost budowania sterownika uruchomi skrypty / mod / modpost z opcją -m. Jeśli jesteś odważny i rzucisz okiem na źródło scripts / mod / modpost.c , zobaczysz, że opcja -m dodaje symbol _module_layout_ z vmlinux, jednak jeśli nie masz Modules.symvers z twojego jądra, nie otrzymasz wartości CRC dla tego symbolu i pojawi się ten komunikat o błędzie.

Istnieją więc dwa sposoby na obejście tego.

1) uruchom pełną wersję działającego jądra, aby wygenerować Modules.symvers, a następnie przebuduj moduł. [http://www.mjmwired.net/kernel/Documentation/kbuild/modules.txt][1]

51  === 2. How to Build External Modules
52  
53  To build external modules, you must have a prebuilt kernel available
54  that contains the configuration and header files used in the build.
55  Also, the kernel must have been built with modules enabled. If you are
56  using a distribution kernel, there will be a package for the kernel you
57  are running provided by your distribution.
58  
59  An alternative is to use the "make" target "modules_prepare." This will
60  make sure the kernel contains the information required. The target
61  exists solely as a simple way to prepare a kernel source tree for
62  building external modules.
63  
64  NOTE: "modules_prepare" will not build Module.symvers even if
65  CONFIG_MODVERSIONS is set; therefore, a full kernel build needs to be
66  executed to make module versioning work.

2) Inną opcją jest powiedzenie głupiemu modprobe, aby po prostu zignorował te badziewie i po prostu załadował moduł:

modprobe -f <module>

Preferuję opcję 2 :)

Dan Gora
źródło
1
+1 za „powiedz głupiemu modprobe, żeby po prostu zignorował te badziewie i po prostu załadował moduł”.
Hayri Uğur Koltuk
Próbowałem 2 i okazało się, że moduł nie ładuje się automatycznie podczas rozruchu. czy istnieje sposób na -f podczas uruchamiania?
Justin Zhang,
17

Zainstaluj oba pakiety linux-headersi linux-sourceodpowiadające twojemu jądru. Na przykład dla jądra 3.2.0-27-generic-paepotrzebujesz:

  1. linux-headers-3.2.0-27-generic-pae i
  2. linux-source-3.2.0-27-generic-pae.

W przypadku, gdy wersja powyższych pakietów nie odpowiada bieżącej wersji jądra, musisz zastąpić $(uname -r)ciągiem wersji z zainstalowanego pakietu jądra z góry.
W powyższym przykładzie wersja pakietu to 3.2.0-27-generic-pae. Gdy uruchomisz, uname -ra jego wynik jest inny 3.2.0-27-generic-pae, musisz zastąpić każdy z nich $(uname -r)poniżej, aby dopasować ciąg wersji z zainstalowanych pakietów.

  1. cd /usr/src/linux-source-$Version i rozpakuj archiwum .tar.bz2 na miejscu i włóż cd do wyodrębnionego katalogu - myślę, że już to zrobiłeś
  2. cp /boot/config-$(uname -r) .config do katalogu źródłowego jądra
  3. cp /usr/src/linux-headers-$(uname -r)/Module.symvers . do katalogu źródłowego jądra

Po wykonaniu tej czynności w katalogu źródłowym jądra wykonaj następujące czynności:

  1. make prepare
  2. make scripts
  3. make M=drivers/usb/serial- zmień ścieżkę po M=według własnych potrzeb

Niestety nie wiem, jak zbudować konkretny moduł, pozostając Module.symversnietkniętym. Robi make drivers/usb/serial/option.ko, na przykład, zabija Module.symversplik i skończyć z oryginalnego problemu. Użycie M=parametru nie zabija go, ale musisz zbudować wszystkie moduły w określonej ścieżce - a ja jeszcze nie znalazłem sposobu na obejście tego.

Radu C.
źródło
Wydaje się, że najlepszym sposobem, aby robić rzeczy, w przypadku jesteś kompilacji modułu w tej samej wersji drzewa ...
Trevino
2

Musisz użyć dokładnie identycznej konfiguracji jądra przed uruchomieniem make prepare. Ponadto, jeśli budujesz go z drzewa, musisz budować go w oparciu o dokładnie identyczne nagłówki jądra pasujące do aktualnie uruchomionego jądra (lub docelowego, jeśli nie uruchamiasz go w czasie kompilacji).

Daniel T Chen
źródło
„make mrproper”, „cp / boot / config - $ (uname -r) .config”, „make oldconfig”, „make ready”, „make scripts” Użyłem tych instrukcji do przygotowania kompilacji. Chciałbym wiedzieć, czy skopiowałem prawidłowy plik konfiguracyjny? wygląda na to, że istnieje tylko jedna konfiguracja, która pasuje do mojej wersji jądra w / boot /. przepraszam za formatowanie, ponieważ pole komentarza nie ma formatu ....
SpecC
Tak, to wydaje się poprawne. Gdzie wywołujesz kompilację, a jeśli nie z katalogu najwyższego poziomu, jaką wartość SUBDIRS przekazujesz?
Daniel T Chen
Dziękuję za odpowiedź. kiedy próbowałem zbudować usbhid.ko. Użyłem tego polecenia „make module SUBDIRS = drivers / hid / usbhid”
SpecC
kiedy uruchomiłem polecenie „make modules SUBDIRS = drivers / hid / usbhid”, pojawia się następujące ostrzeżenie „OSTRZEŻENIE: brak wersji zrzutu /usr/src/linux-source-2.6.31/Module.symvers; moduły będą miały żadnych zależności i zmian. ”
SpecC
@SpecC Podczas badania problemu zaktualizuj swoje pierwotne pytanie, wykonując odpowiednie kroki. Następnie Dan zaktualizuje swoją odpowiedź, a ty będziesz ją aktualizować, dopóki jej nie wymyślisz
Jorge Castro