Почему этот модуль ядра помечен как постоянный на 2.6.39 - PullRequest
9 голосов
/ 20 сентября 2011

Когда я загружаю этот модуль:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("Dual BSD/GPL");

static int hello_init(void) {
  printk("<1> Hello world!\n");
  return 0;
}

static void hello_exit(void) {
  printk("<1> Bye, cruel world\n");
}


module_init(hello_init);
module_exit(hello_exit);

(от http://www.freesoftwaremagazine.com/articles/drivers_linux?page=0,2)

Модуль помечен как [permanent] в lsmod и не может быть выгружен на 2.6.39-02063904-generic (из Ubuntu PPA ). Но он работает нормально на ядре 2.6.38 по умолчанию. (Оба в Ubuntu 11.04 x86).

Что изменилось в 2.6.39? и что мне нужно изменить в моем коде?

Я пытался выделить более сложную проблему, когда столкнулся с этой проблемой.

EDIT:

По предложению из ответа я отредактировал код, добавив __init и __exit (hello3.c):

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("Dual BSD/GPL");

static int __init hello_init(void) {
  printk("<1> Hello world!\n");
  return 0;
}

static void __exit hello_exit(void) {
  printk("<1> Bye, cruel world\n");
}

module_init(hello_init);
module_exit(hello_exit);

Результат сборки:

make -C /lib/modules/2.6.39-02063904-generic/build M=/home/douglas/kernelmod modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.39-02063904-generic'
Building with KERNELRELEASE = 2.6.39-02063904-generic
  CC [M]  /home/douglas/kernelmod/hello3.o
  Building modules, stage 2.
Building with KERNELRELEASE = 2.6.39-02063904-generic
  MODPOST 8 modules
  CC      /home/douglas/kernelmod/hello3.mod.o
  LD [M]  /home/douglas/kernelmod/hello3.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.39-02063904-generic'

EDIT2:

hello3.mod.c:

#include <linux/module.h>
#include <linux/vermagic.h>
#include <linux/compiler.h>

MODULE_INFO(vermagic, VERMAGIC_STRING);

struct module __this_module
__attribute__((section(".gnu.linkonce.this_module"))) = {
 .name = KBUILD_MODNAME,
 .init = init_module,
#ifdef CONFIG_MODULE_UNLOAD
 .exit = cleanup_module,
#endif
 .arch = MODULE_ARCH_INIT,
};

static const struct modversion_info ____versions[]
__used
__attribute__((section("__versions"))) = {
    { 0xbe4b3e92, "module_layout" },
    { 0xb4390f9a, "mcount" },
    { 0x5e3b3ab4, "printk" },
};

static const char __module_depends[]
__used
__attribute__((section(".modinfo"))) =
"depends=";


MODULE_INFO(srcversion, "D2A869459874C22AB265981");

Также

# grep CONFIG_MODULE_UNLOAD /boot/config-2.6.39-02063904-generic 
CONFIG_MODULE_UNLOAD=y

EDIT3:

Что еще интереснее, этого не происходит с ванильным ядром, которое я сам скомпилировал - это нормально загружает и выгружает модули.

EDIT4:

Я установил сборку Oneiric beta 2 на ВМ, и это ядро ​​3.0.0-11 также не имеет никаких проблем. Так что, похоже, он ограничен ядрами Ubuntu Vanilla PPA. Решить это будет не очень весело.

Ответы [ 4 ]

7 голосов
/ 27 сентября 2011

Итак, после консультации с Canonical, я знаю, в чем проблема:

Основные сборки Ubuntu собраны с помощью цепочки инструментов Hardy, а цепочки инструментов 11.04 и 11.10 несовместимы для сборки модулей ядра вне дерева.

5 голосов
/ 20 сентября 2012

Структура "struct module" зависит от определения HAVE_JUMP_LABEL, которое зависит от определения CC_HAVE_ASM_GOTO, которое зависит от результата сценария gcc-goto.sh, который зависит от используемой версии gcc.В случае несоответствия обратный вызов модуля (деструктор) получает значение NULL, в результате чего модуль помечается как [постоянный].

1 голос
/ 20 сентября 2011

Насколько я могу судить по источникам ядра, модуль помечается как постоянный, если у него есть функция init, но отсутствует функция выхода.

Я не совсем уверен в этом случае, но выВозможно, вы захотите пометить функции инициализации и выхода с __init и __exit соответственно.(также обратите внимание на любые предупреждения, выдаваемые modpost)

0 голосов
/ 26 июня 2014

Эта проблема связана с тем, что старший компилятор gcc генерирует неправильный двоичный формат модуля и приводит к тому, что функция выхода из модуля не может получить надлежащую информацию о выгрузке из ядра.

Вы можете проверить, установлен ли ваш gcc versioni на 4.4, если это, переход на использование 4.6 и проблема будет исправлена:

gcc --version

если версия 4.4, удалите символссылку на / usr / bin / gcc и переназначить ее на /usr/bin/gcc-4.6.Модуль удаления должен работать после перекомпиляции.

...