Linux çekirdeği kaynak kodunda şu işlevi buldum:
static int __init clk_disable_unused(void)
{
// some code
}
Burada ne anlama __initgeldiğini anlayamıyorum .
Linux çekirdeği kaynak kodunda şu işlevi buldum:
static int __init clk_disable_unused(void)
{
// some code
}
Burada ne anlama __initgeldiğini anlayamıyorum .
Yanıtlar:
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)
Bunlar sadece linux kodunun bazı kısımlarını son çalıştırma ikili dosyasında özel alanlara yerleştirmek için makrolardır.
__init, örneğin (veya daha iyisi __attribute__ ((__section__
(".init.text")))bu makronun genişlemesi) derleyiciye bu işlevi özel bir şekilde işaretlemesi talimatını verir. Sonunda, bağlayıcı, ikili dosyanın sonunda (veya başında) bu işarete sahip tüm işlevleri toplar.
Çekirdek başladığında, bu kod yalnızca bir kez çalışır (başlatma). Çalıştırıldıktan sonra, çekirdek bu belleği yeniden kullanmak için boşaltabilir ve çekirdek mesajını göreceksiniz:
Kullanılmayan çekirdek belleğinin serbest bırakılması: 108k serbest bırakıldı
Bu özelliği kullanmak için, bağlayıcıya tüm işaretli işlevleri nerede bulacağını söyleyen özel bir bağlayıcı komut dosyası gerekir.
Bu, çekirdek 2.2 ve sonraki sürümlerin bir özelliğini gösterir. initVe cleanupişlevlerinin tanımlarındaki değişikliğe dikkat edin . __initMakro neden initatılacak fonksiyonu ve hafıza kez kurtulmuş initsürücüleri yerleşik değil yüklenebilir modüller için fonksiyon bittikten. initİşlevin ne zaman çağrıldığını düşünürseniz , bu çok mantıklıdır.
__init, ./include/linux/init.h dosyasında tanımlanan ve genişleyen bir makrodur __attribute__ ((__section__(".init.text"))).
Derleyiciye bu işlevi özel bir şekilde işaretlemesi talimatını verir. Sonunda, bağlayıcı, ikili dosyanın sonunda (veya başlangıcında) bu işaret ile tüm işlevleri toplar. Çekirdek başladığında, bu kod yalnızca bir kez çalışır (başlatma). Çalıştırıldıktan sonra, çekirdek bu belleği yeniden kullanmak için serbest bırakabilir ve çekirdeği
Linux / init.h içindeki yorumu (ve aynı zamanda dokümanları) okuyun .
Ayrıca gcc'nin linux çekirdek kodu için özel olarak yapılmış bazı uzantılara sahip olduğunu bilmelisiniz ve bu makro bunlardan birini kullanıyor gibi görünüyor.
Bir Linux çekirdek modülünü derleyip çekirdeğe yerleştirdiğinizde, yürütülecek ilk işlev __init'tir.Bu işlev temelde bir aygıt sürücüsünün kaydedilmesi vb. Gibi ana işlemleri gerçekleştirmeden önce başlatma gerçekleştirmek için kullanılır. Ters etkiye sahip başka bir işlev vardır __exit, bazı kayıtlı aygıtları veya benzer işlevleri kaldırmak için yeniden kullanılan çekirdek modülünü kaldırdığınızda çağrılır.