«Нет версии символа для module_layout» при попытке загрузить usbhid.ko

27

Я пытаюсь создать свой собственный модуль для usbhid.ko, но после компиляции я не могу загрузить модуль. dmesgговорит no symbol version for module_layout. Мне интересно, в чем проблема? Я уже использовал исходный код ядра, предоставленный Ubuntu, и я также убедился, что версия ядра совпадает.

SpecC
источник

Ответы:

22

В частности, проблема в том, что при сборке модуля в исходном дереве ядра, вероятно, отсутствовал файл Modules.symvers. Система kbuild фактически предупреждает вас об этом, когда вы собираете свой модуль. Если Modules.symvers отсутствует, вы увидите:

Предупреждение: отсутствует дамп версии символов /usr/src/linux-2.6.34-12/Modules.symvers; Модули не будут иметь зависимостей и модификаций.

Если ваше ядро CONFIG_MODVERSIONSвключено, то на этапе сборки вашего драйвера modpost он будет запускать scripts / mod / modpost с параметром -m. Если вы смелы и посмотрите на источник scripts / mod / modpost.c , вы увидите, что опция -m добавляет символ _module_layout_ из vmlinux, однако, если у вас нет Modules.symvers из вашего ядра, вы не получите значение CRC для этого символа, и в результате вы получите это сообщение об ошибке.

Таким образом, есть два способа обойти это.

1) Запустите полную сборку вашего работающего ядра, чтобы сгенерировать Modules.symvers, затем пересоберите ваш модуль. [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) Другой вариант - сказать глупому modprobe просто игнорировать все это дерьмо и просто загрузить ваш модуль в любом случае:

modprobe -f <module>

Я склоняюсь к варианту 2 :)

Дэн Гора
источник
1
+1 за комментарий "глупому modprobe просто игнорировать всю эту чушь и просто загрузить свой модуль в любом случае".
Хайри Угур Колтук
Я попробовал 2 и обнаружил, что модуль не загружается автоматически во время загрузки. есть ли способ -f во время загрузки?
Джастин Чжан
17

Установите оба пакета linux-headersи linux-sourceпакеты, соответствующие вашему ядру. Например для ядра 3.2.0-27-generic-paeвам нужно:

  1. linux-headers-3.2.0-27-generic-pae а также
  2. linux-source-3.2.0-27-generic-pae,

В случае, если версия для вышеуказанных пакетов не соответствует используемой версии ядра, вам нужно заменить $(uname -r)строку версии из установленного пакета ядра сверху.
Для приведенного выше примера версия пакета 3.2.0-27-generic-pae. Когда вы запускаете, uname -rи его вывод отличается, то 3.2.0-27-generic-paeвам нужно заменить каждый из них $(uname -r)ниже, чтобы он соответствовал строке версии из установленных пакетов.

  1. cd /usr/src/linux-source-$Version и распакуйте архив .tar.bz2 на место и перейдите в извлеченный каталог - думаю, вы уже сделали это
  2. cp /boot/config-$(uname -r) .config в исходный каталог ядра
  3. cp /usr/src/linux-headers-$(uname -r)/Module.symvers . в исходный каталог ядра

После того, как вы это сделаете, в исходном каталоге ядра сделайте следующее:

  1. make prepare
  2. make scripts
  3. make M=drivers/usb/serial- измените путь после, M=чтобы удовлетворить ваши потребности

К сожалению, я не знаю, как создать конкретный модуль, не Module.symversтрогая его. Выполнение make drivers/usb/serial/option.ko, например, убивает Module.symversфайл, и вы в конечном итоге с вашей первоначальной проблемой. Использование M=параметра не убивает его, но вы должны собрать все модули по указанному пути - и я пока не нашел обходного пути.

Раду С
источник
Кажется, это лучший способ сделать что-то, если вы компилируете модуль в одной и той же древовидной версии ...
Тревиньо
2

Вы должны использовать точно идентичную конфигурацию ядра перед запуском make prepare. Кроме того, если вы собираете его вне дерева, вам нужно строить его из точно идентичных заголовков ядра, соответствующих вашему текущему работающему ядру (или целевому, если вы не запускаете его во время компиляции).

Даниэль Т Чен
источник
"make mrproper", "cp / boot / config - $ (uname -r) .config", "make oldconfig", "make prepare", "make scripts". Я использовал эти инструкции для подготовки компиляции. Я хотел бы знать, скопировал ли я правильный файл конфигурации? Похоже, что есть только один конфиг, который соответствует моей версии ядра в / boot /. извините за форматирование, так как поле для комментариев не имеет формата ....
SpecC
Да, это кажется правильным. Где вы вызываете сборку, и если не из каталога верхнего уровня, какое значение SUBDIRS вы передаете?
Даниэль Т Чен
Спасибо за ответ. когда я пытался построить usbhid.ko. Я использовал эту команду «сделать модули SUBDIRS = drivers / hid / usbhid»
SpecC
Когда я запустил команду «make modules SUBDIRS = drivers / hid / usbhid», я получил следующее предупреждение «ПРЕДУПРЕЖДЕНИЕ: дамп версии символа /usr/src/linux-source-2.6.31/Module.symvers отсутствует; модули будут иметь без зависимостей и модификаций. "
SpecC
@SpecC По мере изучения вашей проблемы обновите исходный вопрос с помощью шагов, которые вы предпринимаете. Затем Дэн обновит свой ответ, и вы будете обновлять его до тех пор, пока не выясните его, а не строку комментариев, которые в конечном итоге будут похоронены. Дополнительные советы можно найти в руководстве: meta.askubuntu.com/questions/257/how-does-ask работа
Хорхе Кастро