.init
/ .fini
kullanımdan kaldırılmadı. Hala ELF standardının bir parçası ve sonsuza kadar olacağını söyleyebilirim. Kodu .init
/ .fini
kod yüklenir zaman boş / yükleyici / çalışma bağlayıcı tarafından çalıştırılır. Yani her bir ELF yükü (örneğin, paylaşılan bir kütüphane) kodu .init
çalıştırılacaktır. Hala aynı şeyi başarmak için bu mekanizmayı kullanmak hala mümkündür __attribute__((constructor))/((destructor))
. Eski okul ama bazı faydaları var.
.ctors
/ .dtors
Mekanizması örneğin system-rtl / loader / linker-script desteği gerektirir. Bu, tüm sistemlerde mevcut olmaktan çok uzaktır, örneğin kodun çıplak metal üzerinde yürütüldüğü derin gömülü sistemler. Yani __attribute__((constructor))/((destructor))
, GCC tarafından desteklense bile , onu düzenlemek için bağlayıcıya ve çalıştırmak için yükleyiciye (veya bazı durumlarda önyükleme koduna) bağlı olacağı kesin değildir. Kullanım için .init
/ .fini
yerine, kolay yolu bağlayıcı bayraklarını kullanmaktır: -init & -fini (GCC komut satırından yani sözdizimi olacaktır -Wl -init my_init -fini my_fini
).
Her iki yöntemi de destekleyen sistemde, olası bir fayda, kodun .init
önce çalıştırılması .ctors
ve kodun .fini
sonra çalıştırılmasıdır .dtors
. Sipariş alakalı ise, başlangıç / çıkış işlevlerini ayırt etmenin en az bir ham ama kolay yoludur.
En büyük dezavantaj, her yüklenebilir modül başına birden fazla _init
ve bir _fini
işleve kolayca sahip olamamanız ve muhtemelen kodu .so
motive edilenden daha fazla parçalamanız gerekmesidir. Bir diğeri, yukarıda açıklanan bağlayıcı yöntemini kullanırken, orijinal _init ve _fini
varsayılan işlevlerin (tarafından sağlanan crti.o
) değiştirilmesidir. Burası genellikle her türlü başlatma işleminin gerçekleştiği yerdir (Linux'ta bu, global değişken atamanın başlatıldığı yerdir). Burada anlatılan bir yol
Yukarıdaki bağlantıda _init()
, hala yerinde olduğu için orijinaline basamaklı bir şeye ihtiyaç duyulmadığına dikkat edin. call
Montaj ancak çizgi içi x86 anımsatıcı ve montaj (örneğin ARM gibi) birçok başka mimariler için tamamen farklı olmazdı bir işlevi çağırmak olduğunu. Yani kod şeffaf değil.
.init
/ .fini
ve .ctors
/ .detors
mekanizmaları benzerdir, ancak tam olarak değildir. Kod .init
/ .fini
ishal "olduğu gibi". Yani .init
/ içinde birkaç fonksiyona sahip olabilirsiniz .fini
, ancak AFAIK'i, birçok küçük .so
dosyada kodu bozmadan tamamen şeffaf olarak saf C'ye koymak onları sözdizimsel olarak zordur .
.ctors
/ .dtors
Farklı bir şekilde düzenlenir .init
/ ' .fini
. .ctors
/ .dtors
bölümlerinin her ikisi de yalnızca işlevlere işaret eden tablolardır ve "arayan" her işlevi dolaylı olarak çağıran sistem tarafından sağlanan bir döngüdür. Yani döngü arayan mimariye özgü olabilir, ancak sistemin bir parçası olduğu için (eğer varsa) önemli değil.
Aşağıdaki snippet, .ctors
işlev dizisine temelde olduğu gibi yeni işlev işaretçileri ekler __attribute__((constructor))
(yöntem birlikte bulunabilir) __attribute__((constructor)))
.
#define SECTION( S ) __attribute__ ((section ( S )))
void test(void) {
printf("Hello\n");
}
void (*funcptr)(void) SECTION(".ctors") =test;
void (*funcptr2)(void) SECTION(".ctors") =test;
void (*funcptr3)(void) SECTION(".dtors") =test;
Tamamen farklı bir kendi icat ettiği bölüme fonksiyon göstergeleri de eklenebilir. Bu durumda değiştirilmiş bir bağlayıcı komut dosyası ve yükleyiciyi .ctors
/ .dtors
döngüyü taklit eden ek bir işlev gereklidir. Ancak bununla birlikte, yürütme sırası üzerinde daha iyi bir kontrol elde edilebilir, bağımsız değişken ve dönüş kodu işleme eta eklenebilir (Örneğin, bir C ++ projesinde, global kuruculardan önce veya sonra çalışan bir şeye ihtiyaç duymanız faydalı olacaktır).
__attribute__((constructor))/((destructor))
Mümkün olduğunca tercih ederim , hile gibi hissetse bile basit ve zarif bir çözüm. Benim gibi çıplak metal kodlayıcılar için, bu her zaman bir seçenek değildir.
Bağlayıcılar ve yükleyiciler kitabında bazı iyi referans .
#define __attribute__(x)
) kolayca yapılabilir . Birden fazla özelliğiniz varsa, örneğin,__attribute__((noreturn, weak))
yalnızca bir köşeli parantez kümesi olsaydı "makro çıkışı" zor olurdu.