Dinamik bağlantı - Linux Vs. pencereler


10

Windows altında, MSVC'de bir DLL projesinde C / C ++ kodunu derlediğimde 2 dosya alıyorum:

  1. MyDll.dll
  2. MyDll.lib

anladığım kadarıyla MyDll.libdll fonksiyonları yerleri gösteren işaretçiler tablosu bir tür içerir nerede . Bu dll kullanırken, örneğin bir exe dosyasında, MyDll.libbağlantı sırasında exe dosyasına gömülü böylece çalışma zamanında fonksiyonları nerede bulunur MyDll.dllve bunları kullanabilirsiniz "bilir" .

Ama aynı kodu Linux altında derlersem, sadece bir dosya MySo.soalmıyorum MySo.a( libLinux'ta dosyaya eşdeğer ), bu yüzden Linux altında yürütülebilir bir dosya MySo.so, bağlantı sırasında hiçbir şey gömülü değilse , fonksiyonların nerede olduğunu nasıl bilebilir ?

Yanıtlar:


1

Linux'ta, bağlayıcı (dinamik bağlayıcı değil) bağlantı sırasında belirtilen paylaşılan kütüphaneleri arar ve yürütülebilir dosyada bunlara referanslar oluşturur. Dinamik bağlayıcı bu yürütülebilir dosyaları yüklediğinde, ihtiyaç duydukları paylaşılan kütüphaneleri belleğe yükler ve ikili dosyaların çalışmasına izin veren sembolleri çözer.

MySo.a, oluşturulduysa, aslında Windows'ta kullanılan "simge arama tabloları" yerine doğrudan ikili dosyaya bağlanacak sembolleri içerir.

rustyx'in cevabı , Windows'taki süreci benden daha iyi açıklıyor; Windows'u kullandığımdan bu yana uzun zaman geçti.


1
"Windows farklı bir yaklaşım benimsiyor ... işletim sistemine sembollerin DLL'de tam olarak nerede olduğunu belirtin" - bu , wiki ile çelişir , bu da wiki ile çelişir. ordinals kullanın (kitaplık kullanıcılarını, kitaplık değiştiğinde kodlarını yeniden derlemeye ve yeniden konuşlandırmaya zorladığı için hiç kimsenin yapamayacağı doğrudan adres bağlaması kullanılmadığı sürece).
yugr

@ yugr O kısmı kaldırdım, ben zaten payetten tutuyordum.
SS Anne

4

MSVC bağlayıcısı, bir .EXE veya bir .DLL oluşturmak için nesne dosyalarını (.obj) ve nesne kitaplıklarını (.lib) birbirine bağlayabilir.

Bir DLL ile bağlantı kurmak için, MSVC'deki işlem, C işlev adları ile DLL'nin dışa aktarma tablosu arasında bir tutkal görevi gören bir içe aktarma kitaplığı (.LIB) kullanmaktır (DLL'de bir işlev ada göre dışa aktarılabilir veya tarafından sıralı - ikincisi sıklıkla) belgesiz API'ler için kullanıldı.

Ancak, çoğu durumda DLL verme tablosu tüm işlev adlarına sahiptir ve bu nedenle alma kitaplığı (.LIB) büyük ölçüde gereksiz bilgiler içerir (" ABC alma işlevi -> ABC verme işlevi " vb.). Mevcut bir .DLL dosyasından bir .LIB oluşturmak
bile mümkündür .

Diğer platformlardaki bağlayıcılarda bu "özellik" yoktur ve doğrudan dinamik kitaplıklarla bağlantı kurabilirler.


"Diğer platformlardaki bağlayıcıların bu özelliği yoktur" - gecikmeli yükleme ve diğer güzellikler elde etmek için uygulanması kolaydır (örn. Implib.so bunu Linux için yapar).
yugr

@ yugr: "özellik" tırnak içinde budur - genellikle yapmak istediğiniz bir şey değildir ve Windows üzerinde yapmanız gereken ekstra bir iştir.
Chris Dodd

1

Gördüğünüz fark daha çok bir uygulama detayıdır - hem Linux hem de Windows benzer şekilde çalışır - kodunuz çalıştırılabilirinizde statik olarak bağlı olan bir saplama işlevini çağırır ve bu saplama daha sonra gerekirse DLL / shlib'i yükler ( gecikirse) yükleme ilk çağrı program başlatılır) ve () ile sembol giderir, aksi takdirde kütüphane yüklenir GetProcAddress/ ' dlsym.

Tek fark, Linux'ta uygulamanızı dinamik kitaplıkla (kitaplık bunları oluşturmak için yeterli bilgi içerir) bağladığınızda bu saplama işlevlerinin (PLT saplamaları olarak adlandırılır) dinamik olarak üretilmesidir, oysa Linux'ta DLL'nin kendisi olduğunda oluşturulur. ayrı bir .libdosyada oluşturuldu.

İki yaklaşım o kadar benzer ki, Linux'ta Windows içe aktarma kitaplıklarını taklit etmek aslında mümkün ( Implib.so projesine bakın ).


0

Linux'ta, MySo.sobağlayıcıya geçersiniz ve yalnızca bağlantı aşaması için gerekenleri çıkarabilir MySo.sove çalışma zamanında gerekli olan bir referansı koyabilirsiniz .


-3

.dllveya .sopaylaşılan kütüphaneler (çalışma zamanında bağlı), .ave .libstatik bir kitaplık (derleme zamanında bağlı). Bu Windows ve Linux arasında bir fark yok.

Aralarındaki fark, nasıl ele alındıklarıdır. Not: fark sadece gümrükte, nasıl kullanılırlar. Linux'u Windows yolunda oluşturmak çok zor olmazdı, bunun tersi de pratikte hiç kimse bunu yapmıyor.

Bir dll kullanırsak veya kendi ikili dosyamızdan bile bir işlev çağırırsak, basit ve net bir yol vardır. Örneğin, C'de şunu görüyoruz:

int example(int x) {
  ...do_something...
}

int ret = example(42);

Ancak asm düzeyinde birçok fark olabilir. Örneğin, x86'da, bir callopcode yürütülür ve 42yığın üzerinde verilir. Veya bazı kayıtlarda. Veya herhangi bir yerde. Kimse dll yazmadan önce , nasıl kullanılacağını bilmiyor. Ya da projelerin bunu nasıl kullanmak isteyeceği, şu anda var olmayan bir derleyici (veya bir dilde!) İle yazılmış olabilir (veya dll geliştiricileri için bilinmemektedir).

Örneğin, varsayılan olarak, hem C hem de Pascal bağımsız değişkenleri yığından koyar (ve dönüş değerlerini alır) - ancak bunu farklı sırayla yaparlar . Ayrıca, derleyicilerdeki bazı optimizasyonlarla kayıtlardaki işlevleriniz arasında argüman alışverişi yapabilirsiniz.

Doğru gördüğünüz gibi, Windows özel bir dll oluşturmak, biz de minimal oluşturmak .a /.lib . Bu minimal statik kütüphane sadece bir sarıcı, o dll sembolleri (fonksiyonları) içinden ulaşılır. Bu, gerekli asm düzeyi arama dönüşümlerini yapar.

Avantajı uyumluluktur. Bunun dezavantajı, yalnızca bir .dll dosyanız varsa, işlevlerinin nasıl çağrılmasını istediğini anlamak için zor bir zamanınız olabilir. Bu dlls kullanımını bir korsanlık görevi yapar,Eğer dll geliştiricisi size vermezse, bu.a . Bu nedenle, çoğunlukla kapalılık amaçlarına hizmet eder, örneğin SDK'lar için ekstra nakit elde etmek daha kolaydır.

Bir başka dezavantajı, dinamik bir kütüphane kullansanız bile, bu küçük sargıyı statik olarak derlemeniz gerekir.

Linux'ta dll'lerin ikili arayüzü standarttır ve C kuralını izler. Bu nedenle, hayır .agerekli ve paylaşılan kütüphaneler arasında ikili uyumluluk var, karşılığında microsoft custom'un avantajlarına sahip değiliz.


1
Lütfen saplama işlevlerinin bağımsız değişken sırasını değiştirebileceğine dair bir prodüksiyon bağlantısı sağlayın. Bunu daha önce hiç duymamıştım ve performansın ne kadar büyük olacağı düşünüldüğünde inanmak zor.
yugr

@yugr Basit bir kayıt / yığın yeniden sıralaması performans yükü değildir. Eğer msvc-derlenmiş ikili dosyalardan msvc-derlenmiş dlls kullanırsanız, o zaman çok fazla olmayacak, ama olabilir.
peterh - Monica'yı eski durumuna döndür

1
Bunu tartışabiliriz, ancak haklı olmanız durumunda, saplama işlevlerinin önemsiz argümanların işlenebileceğine dair kanıtlar sağlamak kolay olmalıdır (ve sadece kukla trambolinlerden daha fazlası olabilir).
yugr

@yugr Saplamaların, dll'nin önemsiz işlemeyi önemsiz hale getiren işlev imzalarına erişimi vardır.
peterh - Monica'yı eski durumuna döndür

1
Yanıtınızı yalnızca içe aktarma kitaplığının ne yaptığına ilişkin birkaç kanıtla tamamlamanızı öneririm (çünkü bazı iddialar sorgulanabilir).
yugr
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.