'Statik olarak bağlı' ve 'dinamik olarak bağlı' ne anlama geliyor?


230

Sık sık 'statik olarak bağlı' ve 'dinamik olarak bağlı' terimlerini duyuyorum, genellikle C , C ++ veya C # ile yazılmış koda başvuruyor . Onlar nedir, tam olarak neden bahsediyorlar ve ne ile bağlantı kuruyorlar?

Yanıtlar:


446

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.cstatik 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.


11
Yanılıyorsam lütfen beni düzeltin, ancak Windows'ta yazılım, dinamik olarak bağlı olsalar bile kendi kitaplıklarını yüklemeye dahil etme eğilimindedir. Paket yöneticisi olan birçok Linux sisteminde, dinamik olarak bağlı birçok kitaplık ("paylaşılan nesneler") aslında yazılımlar arasında paylaşılır.
Paul Fisher

6
@PaulF: Windows ortak kontrolleri, DirectX, .NET vb. . Kendi kodlarını DLL olarak gönderen Win Uygulamaları bunları paylaşma eğilimindedir.
paxdiablo

32
DLL'lerini güncelleyen ve geriye dönük uyumluluğu bozanlar için dokuzuncu cehennem dairesinde ayrılmış özel bir yer var. Evet, arayüzler kaybolursa veya değiştirilirse, dinamik bağlantı bir yığın halinde düşer. Bu yüzden yapılmamalı. Elbette DLL'nize bir function2 () ekleyin, ancak insanlar kullanıyorsa function () değiştirmeyin. Şekilde recode'un fonksiyonu () olan sapın en iyi yolu onu İşlevsiz2 () çağırır, ancak yok fonksiyonun imzasını değiştirmek ().
paxdiablo

1
@ Paul Fisher, bunun geç olduğunu biliyorum ama ... bir Windows DLL ile gelen kütüphane tam kütüphane değil, linker DLL ne içerdiğini söyleyen sadece bir grup taslak. Bağlayıcı daha sonra bilgileri otomatik olarak DLL dosyasını yüklemek için .exe içine koyabilir ve simgeler tanımsız olarak görünmez.
Mark Ransom

1
@Santropedro, lib, import ve DLL isimlerinin anlamı olmak üzere her açıdan haklısınız. Sonek konvansiyon sadece bu yüzden çok fazla okuma (örneğin, DLL bir .dllveya .souzantı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.
paxdiablo

221

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 0x0000ve 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 ) printfmakine 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 ( printfgenellikle 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.


4
Ben de yaptım, ancak sadece 1 cevap seçiyorum.
UnkwnTech

1
Artelius, bu çılgın düşük seviyeli şeylerin nasıl çalıştığına dair açıklamanız hakkında derinlemesine arıyorum. yukarıdaki şeyler hakkında derinlemesine bilgi edinmek için lütfen hangi kitapları okumamız gerektiğini cevaplayınız. teşekkür ederim.
Namratha Patil

1
Üzgünüm, kitap öneremem. Önce montaj dilini öğrenmelisiniz. Ardından Wikipedia bu tür konulara iyi bir genel bakış sunabilir. GNU ldbelgelerine bakmak isteyebilirsiniz .
Artelius

31

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.


16

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 fileikili ü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 libtoolve 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 musltamamı olmasa bile hemen hemen hepsi için statik bağlantı seçenekleri sunar .

Şimdi straceoluşturduğunuz ikili dosya ve program başlamadan önce erişilen kitaplık olmadığını görebilirsiniz:

strace ./simpleprog

Şimdi stracedinamik 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!


2

(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.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.