GNU/Linux >> Znalost Linux >  >> Linux

Rozdíl mezi sdílenými objekty (.so), statickými knihovnami (.a) a DLL (.so)?

Statická knihovna(.a) je knihovna, kterou lze propojit přímo do finálního spustitelného souboru vytvořeného linkerem, je v něm obsažena a není potřeba mít knihovnu v systému, kde bude spustitelný soubor nasazen.

sdílená knihovna (.so) je knihovna, která je propojená, ale není vložená do konečného spustitelného souboru, takže bude načtena při spuštění spustitelného souboru a musí být přítomna v systému, kde je spustitelný soubor nasazen.

Knihovna dynamických odkazů v systému windows(.dll) je jako sdílená knihovna (.so) na linuxu, ale mezi těmito dvěma implementacemi, které souvisejí s OS (Windows vs Linux), jsou určité rozdíly:

DLL může definovat dva druhy funkcí:exportované a interní. Exportované funkce jsou určeny k volání jinými moduly a také z knihovny DLL, kde jsou definovány. Interní funkce jsou obvykle určeny k volání pouze z knihovny DLL, kde jsou definovány.

SO knihovna v Linuxu nepotřebuje speciální exportní příkaz k označení exportovatelných symbolů, protože všechny symboly jsou dostupné pro dotazovací proces.


Vždy jsem si myslel, že knihovny DLL a sdílené objekty jsou jen různé termíny pro stejnou věc – Windows je nazývají DLL, zatímco na systémech UNIX jsou to sdílené objekty, přičemž obecný termín – dynamicky propojená knihovna – zahrnuje obojí (dokonce i funkci otevřít soubor .so v systému UNIX se nazývá dlopen() za 'dynamická knihovna').

Ve skutečnosti jsou propojeny pouze při spuštění aplikace, ale vaše představa o ověření proti souboru záhlaví je nesprávná. Soubor záhlaví definuje prototypy, které jsou nutné pro kompilaci kódu, který používá knihovnu, ale v době propojení se linker podívá do samotné knihovny, aby se ujistil, že funkce, které potřebuje, tam skutečně jsou. Linker musí někde najít těla funkcí v čase propojení, jinak vyvolá chybu. Dělá to TAKÉ za běhu, protože jak správně uvádíte, knihovna samotná se mohla od kompilace programu změnit. To je důvod, proč je stabilita ABI v knihovnách platforem tak důležitá, protože změna ABI je to, co narušuje existující programy kompilované proti starším verzím.

Statické knihovny jsou jen svazky objektových souborů přímo z kompilátoru, stejně jako ty, které si sami vytváříte jako součást kompilace vašeho projektu, takže se stahují a přivádějí do linkeru úplně stejným způsobem a nepoužívané bity jsou klesl přesně stejným způsobem.


Mohu vypracovat podrobnosti o knihovnách DLL ve Windows, abych pomohl objasnit tyto záhady svým přátelům zde v *NIX-land...

DLL je jako soubor sdíleného objektu. Oba jsou obrazy, připravené k načtení do paměti programovým zavaděčem příslušného OS. Obrázky jsou doprovázeny různými bity metadat, které pomáhají linkerům a zavaděčům vytvářet nezbytná asociace a používat knihovnu kódu.

Windows DLL mají exportní tabulku. Exporty mohou být podle názvu nebo podle pozice v tabulce (číselné). Druhá metoda je považována za „starou školu“ a je mnohem křehčí – přebudování DLL a změna pozice funkce v tabulce skončí katastrofou, zatímco pokud je propojení vstupních bodů podle jména, neexistuje žádný skutečný problém. Takže na to zapomeňte jako na problém, ale uvědomte si, že to existuje, pokud pracujete s kódem „dinosauří“ jako je knihovna dodavatelů třetí strany.

Knihovny DLL systému Windows se vytvářejí kompilací a propojováním, stejně jako u EXE (spustitelné aplikace), ale knihovna DLL nemá stát samostatně, stejně jako SO má být používána aplikací, buď prostřednictvím dynamického načítání, nebo pomocí vazby v čase propojení (odkaz na SO je vložen do metadat binárního souboru aplikace a zavaděč programu OS automaticky načte odkazovaná SO). DLL mohou odkazovat na jiné knihovny DLL, stejně jako SO mohou odkazovat na jiné SO.

Ve Windows zpřístupní knihovny DLL pouze konkrétní vstupní body. Těm se říká „exporty“. Vývojář může buď použít speciální klíčové slovo kompilátoru, aby byl symbol externě viditelný (pro ostatní linkery a dynamický zavaděč), nebo mohou být exporty uvedeny v souboru s definicí modulu, který se používá v době propojení, když je samotná DLL se vytváří. Moderní praxí je ozdobit definici funkce klíčovým slovem pro export názvu symbolu. Je také možné vytvořit hlavičkové soubory s klíčovými slovy, které deklarují tento symbol jako symbol, který má být importován z DLL mimo aktuální kompilační jednotku. Pro více informací vyhledejte klíčová slova __declspec(dllexport) a __declspec(dllimport).

Jednou ze zajímavých funkcí knihoven DLL je to, že mohou deklarovat standardní funkci obslužné rutiny „při načtení/vyjmutí“. Kdykoli je knihovna DLL načtena nebo uvolněna, může knihovna DLL provést určitou inicializaci nebo vyčištění, podle okolností. To se krásně hodí na to, že máte DLL jako objektově orientovaného správce prostředků, jako je ovladač zařízení nebo sdílené objektové rozhraní.

Když chce vývojář použít již vytvořenou knihovnu DLL, musí buď odkazovat na "exportní knihovnu" (*.LIB) vytvořenou vývojářem DLL při vytváření knihovny DLL, nebo musí knihovnu DLL explicitně načíst za běhu a vyžádat si adresa vstupního bodu podle názvu prostřednictvím mechanismů LoadLibrary() a GetProcAddress(). Většinu času je propojení se souborem LIB (který jednoduše obsahuje metadata linkeru pro exportované vstupní body DLL) způsob, jak se knihovny DLL používají. Dynamické načítání je obvykle vyhrazeno pro implementaci „polymorfismu“ nebo „konfigurovatelnosti běhového prostředí“ v chování programu (přístup k doplňkům nebo později definovaným funkcím, známým jako „pluginy“).

Způsob, jakým Windows dělá věci, může občas způsobit zmatek; systém používá příponu .LIB k odkazování jak na normální statické knihovny (archivy, jako jsou soubory POSIX *.a), tak na knihovny "export stub" potřebné k navázání aplikace na DLL v době propojení. Měli bychom se tedy vždy podívat, zda soubor *.LIB má soubor *.DLL se stejným názvem; pokud ne, je pravděpodobné, že soubor *.LIB je archiv statické knihovny a neexportuje metadata vazby pro DLL.


Linux
  1. Rozdíl mezi přihlašovacím prostředím a nepřihlašovacím prostředím?

  2. Rozdíl mezi [[ $a ==Z* ]] a [ $a ==Z* ]?

  3. Rozdíl mezi Gtk a Qt aplikacemi?

  1. Rozdíl mezi velikostí bloku a velikostí clusteru?

  2. Rozdíl mezi potrubím a rozšířením příkazů?

  3. Převést statickou knihovnu na sdílenou?

  1. Rozdíl mezi firewallem se sdíleným hardwarem a firewallem pro vyhrazený hardware

  2. Rozdíl mezi $HOME a '~' (tilda)?

  3. rozdíl mezi cgroups a jmennými prostory