Was bedeutet __init im Linux-Kernel-Code?

89

Im Linux-Kernel-Quellcode habe ich diese Funktion gefunden:

static int __init clk_disable_unused(void) 
{
   // some code
}

Hier kann ich nicht verstehen, was __initbedeutet.

Jeegar Patel
quelle

Antworten:

75

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)
Sangeeth Saravanaraj
quelle
55

Dies sind nur Makros, um einige Teile des Linux-Codes in speziellen Bereichen der endgültigen ausführenden Binärdatei zu lokalisieren. __initBeispielsweise (oder besser, __attribute__ ((__section__ (".init.text")))wenn dieses Makro erweitert wird) wird der Compiler angewiesen, diese Funktion auf besondere Weise zu markieren. Am Ende sammelt der Linker alle Funktionen mit dieser Markierung am Ende (oder Anfang) der Binärdatei.

Wenn der Kernel gestartet wird, wird dieser Code nur einmal ausgeführt (Initialisierung). Nach der Ausführung kann der Kernel diesen Speicher freigeben, um ihn wiederzuverwenden. Die Kernel-Meldung wird angezeigt:

Nicht verwendeten Kernelspeicher freigeben: 108.000 freigegeben

Um diese Funktion nutzen zu können, benötigen Sie eine spezielle Linker-Skriptdatei, die dem Linker mitteilt, wo sich alle markierten Funktionen befinden.

Sashoalm
quelle
11
Klug! Das war es also, was "Freigeben von nicht verwendetem Kernel-Speicher: 108k freigegeben" bedeutete. :-) Ich habe mich all die Jahre irgendwie gefragt. Ich nahm an, dass es sich um eine Art Puffer oder etwas anderes handelte, nicht um Code.
Prof. Falken
6

Dies zeigt eine Funktion von Kernel 2.2 und höher. Beachten Sie die Änderung in den Definitionen der initund cleanupFunktionen. Das __initMakro bewirkt, dass die initFunktion verworfen und ihr Speicher freigegeben wird, sobald die initFunktion für integrierte Treiber, jedoch nicht für ladbare Module beendet ist. Wenn Sie darüber nachdenken, wann die initFunktion aufgerufen wird, ist dies absolut sinnvoll.

Quelle

naveen kumar r
quelle
5

__init ist ein in ./include/linux/init.h definiertes Makro, das auf erweitert wird __attribute__ ((__section__(".init.text"))).

Es weist den Compiler an, diese Funktion auf besondere Weise zu markieren. Am Ende sammelt der Linker alle Funktionen mit dieser Markierung am Ende (oder Anfang) der Binärdatei. Wenn der Kernel gestartet wird, wird dieser Code nur einmal ausgeführt (Initialisierung). Nachdem es ausgeführt wurde, kann der Kernel diesen Speicher freigeben, um ihn wiederzuverwenden, und Sie sehen den Kernel

Geoffroy
quelle
3

Lesen Kommentar (und Dokumente zur gleichen Zeit) in linux / init.h .

Sie sollten auch wissen, dass gcc einige Erweiterungen hat, die speziell für Linux-Kernel-Code erstellt wurden, und es sieht so aus, als ob dieses Makro eine davon verwendet.

Elmo
quelle
1

Wenn Sie ein Linux-Kernelmodul kompilieren und in den Kernel einfügen, ist die erste auszuführende Funktion __init. Diese Funktion wird im Wesentlichen verwendet, um die Initialisierung durchzuführen, bevor Sie die Hauptoperationen wie das Registrieren eines Gerätetreibers usw. ausführen. Es gibt eine andere Funktion mit dem gegenteiligen Effekt __exit, das aufgerufen wird, wenn Sie das Kernelmodul entfernen, mit dem erneut ein registriertes Gerät oder eine ähnliche Funktion entfernt wird

Nnaik
quelle