У вихідному коді ядра Linux я знайшов цю функцію:
static int __init clk_disable_unused(void)
{
// some code
}
Тут я не можу зрозуміти, що __initозначає.
У вихідному коді ядра Linux я знайшов цю функцію:
static int __init clk_disable_unused(void)
{
// some code
}
Тут я не можу зрозуміти, що __initозначає.
Відповіді:
include/linux/init.h
/* These macros are used to mark some functions or
* initialized data (doesn't apply to uninitialized data)
* as `initialization' functions. The kernel can take this
* as hint that the function is used only during the initialization
* phase and free up used memory resources after
*
* Usage:
* For functions:
*
* You should add __init immediately before the function name, like:
*
* static void __init initme(int x, int y)
* {
* extern int z; z = x * y;
* }
*
* If the function has a prototype somewhere, you can also add
* __init between closing brace of the prototype and semicolon:
*
* extern int initialize_foobar_device(int, int, int) __init;
*
* For initialized data:
* You should insert __initdata between the variable name and equal
* sign followed by value, e.g.:
*
* static int init_variable __initdata = 0;
* static const char linux_logo[] __initconst = { 0x32, 0x36, ... };
*
* Don't forget to initialize data not at file scope, i.e. within a function,
* as gcc otherwise puts the data into the bss section and not into the init
* section.
*
* Also note, that this data cannot be "const".
*/
/* These are for everybody (although not all archs will actually
discard it in modules) */
#define __init __section(.init.text) __cold notrace
#define __initdata __section(.init.data)
#define __initconst __section(.init.rodata)
#define __exitdata __section(.exit.data)
#define __exit_call __used __section(.exitcall.exit)
Це лише макроси, які дозволяють знаходити деякі частини коду Linux у спеціальних областях у остаточному виконаному двійковому файлі.
__init, наприклад (або краще __attribute__ ((__section__
(".init.text")))цей макрос розширюється до) вказує компілятору позначити цю функцію особливим чином. В кінці компоновщик збирає всі функції з цією позначкою в кінці (або на початку) двійкового файлу.
При запуску ядра цей код запускається лише один раз (ініціалізація). Після його запуску ядро може звільнити цю пам’ять для її повторного використання, і ви побачите повідомлення ядра:
Звільнення невикористаної пам’яті ядра: звільнено 108 тис
Щоб використовувати цю функцію, вам потрібен спеціальний файл сценарію лінкера, який повідомляє лінкеру, де знаходити всі позначені функції.
Це демонструє особливість ядра 2.2 та пізніших версій. Зверніть увагу на зміну у визначеннях функцій initі cleanup. __initМакрос викликає initфункцію , яка буде відкидаються , і її пам'ять звільняється як тільки initфункція обробки для вбудованих драйверів, але не завантажувальних модулів. Якщо ви думаєте про те, коли initфункція викликається, це цілком логічно.
__init - це макрос, визначений у ./include/linux/init.h, який розгортається до __attribute__ ((__section__(".init.text"))).
Він вказує компілятору позначити цю функцію особливим чином. В кінці компоновщик збирає всі функції з цією позначкою в кінці (або початку) двійкового файлу. При запуску ядра цей код запускається лише один раз (ініціалізація). Після його запуску ядро може звільнити цю пам’ять для її повторного використання, і ви побачите ядро
Читайте коментар (і документи , в той же час) в Linux / init.h .
Ви також повинні знати, що gcc має деякі розширення, створені спеціально для коду ядра Linux, і схоже, що цей макрос використовує одне з них.
Коли ви компілюєте та вставляєте в ядро модуль ядра Linux, першою виконуваною функцією є __init. Ця функція в основному використовується для виконання ініціалізації перед виконанням основних операцій, таких як реєстрація драйвера пристрою тощо, існує інша функція з протилежним ефектом __exit, який викликається при видаленні модуля ядра, який знову використовується для видалення зареєстрованого пристрою або будь-якої подібної функції