Yanıtlar:
Kaynak koddan (yazdıklarınız) çalıştırılabilir koda (çalıştırdıklarınıza) ulaşmanın iki aşaması vardır (çoğu durumda yorumlanmış kodu iskonto etmek).
Birincisi, kaynak kodunu nesne modüllerine dönüştüren derleme.
İkincisi, bağlantı, bir çalıştırılabilir oluşturmak için nesne modüllerini bir araya getiren şeydir.
Diğer şeylerin yanı sıra, kaynak kodlarını (veritabanı erişimi, ağ iletişimleri ve grafik kullanıcı arabirimleri için kütüphaneler gibi) görmeden üçüncü taraf kitaplıkların yürütülebilir dosyaya dahil edilmesine izin verilmesi veya farklı dillerde kod derlenmesi ( C ve montaj kodu gibi) ve hepsini birbirine bağlayarak.
Bir dosyayı statik olarak yürütülebilir dosyaya bağladığınızda, o dosyanın içeriği bağlantı zamanında eklenir. Başka bir deyişle, dosyanın içeriği fiziksel olarak çalıştıracağınız yürütülebilir dosyaya eklenir.
Eğer bağladığınızda dinamik , dosyaya bir işaretçi yürütülebilir dahildir ve söz konusu dosyanın içeriği, bağlantı zaman dahil değildir (örneğin, dosyanın dosya adı) 'de bağlanmaktadır. Daha sonra zaman sadece var çalıştırmak bu dinamik bağlantılı dosyalar halinde satın alınan ve sadece diskte yürütülebilir değil birinin bellek kopyasına satın olduğunuzu yürütülebilir.
Temelde bir ertelenmiş bağlantı yöntemidir. İçinde bir işlevi çağırmaya çalışana kadar dinamik olarak bağlı dosyayı getirmeyecek daha ertelenmiş bir yöntem (bazı sistemlerde geç bağlama adı verilir) vardır.
Statik olarak bağlı dosyalar, bağlantı sırasında yürütülebilir dosyaya 'kilitlenir', böylece hiçbir zaman değişmezler. Yürütülebilir dosya tarafından başvurulan dinamik olarak bağlı bir dosya yalnızca diskteki dosyayı değiştirerek değişebilir.
Bu, kodu yeniden bağlamak zorunda kalmadan işlev güncellemelerine izin verir; yükleyici her çalıştırdığınızda yeniden bağlanır.
Bu hem iyi hem de kötü - bir yandan, daha kolay güncellemeler ve hata düzeltmeleri sağlar, diğer yandan güncellemeler uyumsuzsa programların çalışmamasına yol açabilir - bu bazen bazı insanların korkunç "DLL cehenneminden" sorumludur dinamik olarak bağlantılı bir kütüphaneyi uyumlu olmayan bir kütüphaneyle değiştirirseniz uygulamaların bozulabileceğini belirtin (bunu yapan geliştiriciler bu arada avlanmayı ve ciddi şekilde cezalandırılmayı beklemelidir).
Bir olarak örneğin , onların derleme bir kullanıcının davasına diyelim göz main.c
statik ve dinamik bağlantı için dosyayı.
Phase Static Dynamic
-------- ---------------------- ------------------------
+---------+ +---------+
| main.c | | main.c |
+---------+ +---------+
Compile........|.........................|...................
+---------+ +---------+ +---------+ +--------+
| main.o | | crtlib | | main.o | | crtimp |
+---------+ +---------+ +---------+ +--------+
Link...........|..........|..............|...........|.......
| | +-----------+
| | |
+---------+ | +---------+ +--------+
| main |-----+ | main | | crtdll |
+---------+ +---------+ +--------+
Load/Run.......|.........................|..........|........
+---------+ +---------+ |
| main in | | main in |-----+
| memory | | memory |
+---------+ +---------+
Statik durumda, ana program ve C çalışma zamanı kitaplığının bağlantı sırasında birbirine bağlandığını görebilirsiniz (geliştiriciler tarafından). Kullanıcı genellikle yürütülebilir dosyayı yeniden bağlayamadığından, kitaplığın davranışına bağlı kalır.
Dinamik durumda, ana program C çalışma zamanı içe aktarma kitaplığıyla bağlantılıdır (dinamik kitaplıkta ne olduğunu bildiren ancak aslında tanımlamayan bir şey). Bu, gerçek kod eksik olsa bile linkerin bağlanmasını sağlar.
Daha sonra çalışma zamanında, işletim sistemi yükleyicisi ana programın C çalışma zamanı DLL'si (dinamik bağlantı kitaplığı veya paylaşılan kitaplık veya diğer adlandırma) ile geç bir bağlantı yapar.
C çalışma zamanının sahibi, güncellemeler veya hata düzeltmeleri sağlamak için istediği zaman yeni bir DLL dosyası bırakabilir. Daha önce belirtildiği gibi, bunun hem avantajları hem de dezavantajları vardır.
.dll
veya .so
uzantısı olabilir) - cevabı tam bir açıklama olmaktan ziyade kavramları açıklamak olarak düşünün . Ve metne göre, bu sadece C çalışma zamanı dosyaları için statik ve dinamik bağlantıyı gösteren bir örnektir, bu yüzden evet, hepsinde `crt budur.
Ben bu soruya iyi bir cevap bağlama açıklamak gerektiğini düşünüyorum olduğunu .
Bazı C kodlarını derlediğinizde (örneğin), makine diline çevrilir. Sadece çalıştırıldığında, işlemcinin "git", bellek okuma, bellek yazma, bu tür bir şey eklemesine, çıkarmasına, karşılaştırmasına neden olan bir bayt dizisi. Bu şeyler nesne (.o) dosyalarında saklanır.
Uzun zaman önce, bilgisayar bilimcileri bu "altyordam" şeyi icat ettiler. Yürütme-bu-öbek-of-kod ve dönüşümsüz burada. En faydalı altyordamların özel bir yerde saklanabileceğini ve ihtiyaç duyan herhangi bir program tarafından kullanılabileceğini fark etmeden çok uzun sürmedi.
Şimdi ilk günlerde programcılar bu altyordamların bulunduğu bellek adresini delmek zorunda kalacaklardı. Gibi bir şey CALL 0x5A62
. Bu bellek adreslerinin değiştirilmesi gerektiğinde sıkıcı ve sorunluydu.
Böylece süreç otomatikleştirildi. Çağıran bir program printf()
yazıyorsunuz ve derleyici bellek adresini bilmiyor printf
. Derleyici sadece yazar CALL 0x0000
ve nesne dosyasına "bu 0x0000 yerine printf bellek konumuyla değiştirmek gerekir" diyen bir not ekler .
Statik bağlantı, bağlayıcı programın (GNU olanı ld olarak adlandırılır ) printf
makine kodunu doğrudan yürütülebilir dosyanıza eklediği ve 0x0000'ü adresiyle değiştirdiği anlamına gelir printf
. Bu, yürütülebilir dosya oluşturulduğunda gerçekleşir.
Dinamik bağlantı, yukarıdaki adımın gerçekleşmediği anlamına gelir. Yürütülebilir dosya hala "0x000 printf bellek konumu ile değiştirmek gerekir" yazan bir not var. İşletim sisteminin yükleyici ihtiyaçları, printf kodunu bulmak belleğe yüklemek ve ÇAĞRI adresini düzeltmek için Program her çalıştırıldığında .
Programların statik olarak bağlanacak bazı işlevleri ( printf
genellikle statik olarak bağlı olan standart kitaplık işlevleri ) ve dinamik olarak bağlı diğer işlevleri çağırması yaygındır . Statik olanlar, yürütülebilir dosyanın "parçası" olur ve dinamik olanlar da yürütülebilir dosya çalıştırıldığında "katılır".
Her iki yöntemin de avantajları ve dezavantajları vardır ve işletim sistemleri arasında farklılıklar vardır. Ama sen sormadığın için, burada bitireceğim.
ld
belgelerine bakmak isteyebilirsiniz .
Statik olarak bağlı kütüphaneler derleme zamanında bağlanır. Dinamik olarak bağlı kütüphaneler çalışma zamanında yüklenir. Statik bağlantı, kütüphane bitini yürütülebilir dosyaya ekler. Dinamik bağlantı yalnızca kütüphaneye referans olarak kullanılır; dinamik kitaplığın bitleri başka yerlerde bulunur ve daha sonra değiştirilebilir.
Yukarıdaki yazıların hiçbiri aslında bir şeyi statik olarak nasıl bağlayacağınızı ve doğru bir şekilde yaptığınızı görmediğinden, bu sorunu ele alacağım:
Basit bir C programı
#include <stdio.h>
int main(void)
{
printf("This is a string\n");
return 0;
}
C programını dinamik olarak bağlayın
gcc simpleprog.c -o simpleprog
Ve file
ikili üzerinde çalıştırın :
file simpleprog
Bu, dinamik olarak birbirine bağlı bir şey olduğunu gösterecektir:
"simpleprog: ELF 64 bit LSB yürütülebilir, x86-64, sürüm 1 (SYSV), dinamik olarak bağlı (paylaşılan kütüphaneleri kullanır), GNU / Linux 2.6.26, BuildID [sha1] = 0xf715572611a8b04f686809d90d1c0d75c6028f0f, soyulmamış"
Bunun yerine programı bu sefer statik olarak bağlayalım:
gcc simpleprog.c -static -o simpleprog
Bu statik olarak bağlı ikili dosya üzerinde çalışan dosya şunu gösterir:
file simpleprog
"simpleprog: ELF 64 bit LSB yürütülebilir, x86-64, sürüm 1 (GNU / Linux), statik olarak bağlı, GNU / Linux 2.6.26, BuildID [sha1] = 0x8c0b12250801c5a7c7434647b7dc65a644d6132b, soyulmamış"
Ve mutlu bir şekilde statik olarak bağlantılı olduğunu görebilirsiniz. Ne yazık ki, tüm kütüphanelerin bu şekilde statik olarak bağlanması kolay değildir libtool
ve nesne kodunu ve C kütüphanelerini elle kullanmak veya bağlamak için daha fazla çaba gerektirebilir .
Neyse ki birçok gömülü C kütüphanesi, kütüphanelerinin musl
tamamı olmasa bile hemen hemen hepsi için statik bağlantı seçenekleri sunar .
Şimdi strace
oluşturduğunuz ikili dosya ve program başlamadan önce erişilen kitaplık olmadığını görebilirsiniz:
strace ./simpleprog
Şimdi strace
dinamik olarak bağlı programın çıktısıyla karşılaştırın ve statik olarak bağlanmış versiyonun strace'sinin çok daha kısa olduğunu göreceksiniz!
(C # bilmiyorum ama bir VM dili için statik bir bağlantı kavramına sahip olmak ilginç)
Dinamik bağlantı, yalnızca programınızdan referans aldığınız gerekli bir işlevselliğin nasıl bulunacağını bilmeyi içerir. Dil çalışma zamanı veya işletim sistemi dosya sistemini, ağı veya derlenmiş kod önbelleğini referansla eşleştirerek bir parça kod arar ve ardından yeniden yerleştirme gibi bellekteki program görüntünüze entegre etmek için birkaç önlem alır. Hepsi çalışma zamanında yapılır. Manuel olarak veya derleyici tarafından yapılabilir. Dağınıklık riski ile güncelleme yeteneği vardır (yani, DLL cehennem).
Statik bağlantı derleme zamanında yapılır, derleyiciye tüm fonksiyonel parçaların nerede olduğunu söyler ve bunları entegre etmesini söylersiniz. Yeniden derleme olmadan arama, belirsizlik ve güncelleme yeteneği yoktur. Tüm bağımlılıklarınız fiziksel olarak program görüntünüzle birdir.