2013-11-13 4 views
0

вот простой программный код модуля.Программирование модулей в linux

#include <linux/module.h> /* Needed by all modules */ 
#include <linux/kernel.h> /* Needed for KERN_INFO */ 
#include <linux/init.h>  /* Needed for the macros */ 

static int hello3_data __initdata = 3; 

static int __init hello_3_init(void) 
{ 
    printk(KERN_INFO "Hello, world %d\n", hello3_data); 
    return 0; 
} 

static void __exit hello_3_exit(void) 
{ 
    printk(KERN_INFO "Goodbye, world %d\n",hello3_data); 
} 

module_init(hello_3_init); 
module_exit(hello_3_exit); 

Я инициализирует переменную с __initdata макро и функции с __init. когда я сделал insmod, модуль был вставлен, и я смог увидеть сообщение журнала (/ var/log/messages). Но, когда я сделал rmmod, он не смог его удалить, и он говорит Resource busy.

My question is does the `modules_init` function cleans the memory of `hello3_data`?? 

or it is done by `module_exit`??. 

Кто-то, пожалуйста, объясните.

ответ

3

При использовании varialble hello3_data вы используете модификатор __initdata, который указывает, что переменная должна использоваться только в функции __init.

Попробуйте пересобрать модуль ядра с опциями, как make CONFIG_DEBUG_SECTION_MISMATCH=y и вы увидите предупреждения, как это:

ВНИМАНИЕ: /home/pengyu/temp/yusen/test_mod.o(.exit.text+0x3): Несоответствие раздела в ссылке от функции cleanup_module() к переменной .init.data: hello3_data
Функция __exit cleanup_module() ссылается на переменную __initdata hello3_data.
Это часто наблюдается, когда обработка ошибок в функции выхода использует функциональные возможности в пути инициализации.
Исправление часто заключается в удалении аннотации __initdata hello3_data, поэтому ее можно использовать вне секции инициализации.

Вы можете удалить __initdata и попробуйте снова.

EDITED:

Здесь я пытаюсь представить дополнительные объяснения. Сам модуль ядра находится в формате ELF (Executable and Linkable Format) (с некоторыми разделами, относящимися к модулю ядра). Функция the .init and .fini sections поддерживается линкерами и загрузчиками, включая insmod.

В этом случае атрибут #define __initdata __section(.init.data) работает как __attribute__((section(".init.data"))), который явно указывает, какой раздел данных/функция должна быть помещены в.

В модуле ядра раздел .init не гарантируется сохраняемое после инициализации модуля, и что-либо внутри этого раздела не должно упоминаться вне функции инициализации. Смотрите стр 31 из Linux Device Drivers, Third Edition:

_ инициализации маркера в определении может выглядеть немного странно; это подсказка для ядра, что данная функция используется только во время инициализации. Модуль загружает функцию инициализации после загрузки модуля, делая память доступной для других целей. Существует аналогичный тег ( _initdata) для данных, используемых только во время инициализации. Использование __init и __initdata является необязательным, но это стоит того. Просто не забудьте использовать их для какой-либо функции (или структуры данных), которую вы будете использовать после завершения инициализации.

+0

Спасибо. вот что я хотел знать. BTW написано в/linux/init.h, что '#define __initdata __section (.init.data)', можете ли вы его уточнить, как ядро ​​знает, что оно должно использоваться только в функции '__init'. –

+0

@RajuKundhe См. Мой недавно отредактированный ответ. – starrify

+0

Спасибо большое. это помог. !! –

Смежные вопросы