Vraag Relatie tussen objectbestand en gedeeld objectbestand


wat is de relatie tussen gedeeld object (.so) bestand en object (.o) het dossier?

kan je het alsjeblieft uitleggen via een voorbeeld?


22
2017-07-31 05:12


oorsprong


antwoorden:


Laten we zeggen dat je het volgende C-bronbestand hebt, noem het name.c

#include <stdio.h>
#include <stdlib.h>

void print_name(const char * name)
{
    printf("My name is %s\n", name);
}

Wanneer u het compileert, met cc name.c jij genereert name.o. De .o bevat de gecompileerde code en gegevens voor alle functies en variabelen die zijn gedefinieerd in name.c, evenals een index die is gekoppeld aan de feitelijke code. Als je naar die index kijkt, zeg dan met de nm tool (beschikbaar op Linux en vele andere Unixes) zult u twee items opmerken:

00000000 T print_name
         U printf

Wat dit betekent: er zijn twee symbolen (namen van functies of variabelen, maar geen namen van klassen, structs of soorten) opgeslagen in de .o. De eerste, gemarkeerd met T bevat eigenlijk zijn definitie in name.o. De andere, gemarkeerd met U is slechts een referentie. De code voor print_name is hier te vinden, maar de code voor printf kan niet. Wanneer uw eigenlijke programma wordt uitgevoerd, moet het alle symbolen vinden die referenties zijn en hun definities opzoeken anders objectbestanden om aan elkaar te worden gekoppeld in een compleet programma of complete bibliotheek. Een objectbestand zijn daarom de definities in het bronbestand, omgezet in binaire vorm en beschikbaar voor plaatsing in een volledig programma.

U kunt o-bestanden één voor één aan elkaar koppelen, maar dat doet u niet: er zijn er over het algemeen veel van en het zijn implementatiedetails. Je zou echt liever hebben dat ze allemaal worden verzameld in bundels van gerelateerde objecten, met bekende namen. Deze bundels worden genoemd bibliotheken en ze komen in twee vormen: statisch en dynamisch.

EEN statische bibliotheek (in Unix) is bijna altijd achtervolgd met .a (voorbeelden zijn onder meer libc.a wat de C-kernbibliotheek is, libm.a wat de C math-bibliotheek is) enzovoort. Doorgaan met het voorbeeld waarmee u uw statische bibliotheek zou bouwen ar rc libname.a name.o. Als je rent nm op libname.a je ziet dit:

name.o:
00000000 T print_name
         U printf

Zoals je ziet is het in de eerste plaats een grote tabel met objectbestanden met een indexbevinding alle de namen erin. Net als objectbestanden bevat het zowel de symbolen die in elke worden gedefinieerd .o en de symbolen waarnaar ze verwijzen. Als je zou linken een ander .o (bijv. date.o naar print_date), ziet u een ander item zoals hierboven.

Als u een statische bibliotheek koppelt aan een uitvoerbaar bestand, wordt de volledige bibliotheek ingesloten in het uitvoerbare bestand. Dit is hetzelfde als koppelen in het hele individu .o bestanden. Je kunt je voorstellen dat dit je programma erg groot kan maken, vooral als je veel bibliotheken gebruikt (zoals de meeste moderne toepassingen zijn).

EEN dynamisch of gedeelde bibliotheek is achtervolgd met .so. Het is, net als zijn statische analoog, een grote tabel met objectbestanden, verwijzend naar alle gecompileerde codes. Je zou het bouwen met cc -shared libname.so name.o. Kijken naar met nm is een beetje anders dan de statische bibliotheek. Op mijn systeem staan ​​ongeveer twee dozijn symbolen waarvan er slechts twee zijn print_nameen printf:

00001498 a _DYNAMIC
00001574 a _GLOBAL_OFFSET_TABLE_
         w _Jv_RegisterClasses
00001488 d __CTOR_END__
00001484 d __CTOR_LIST__
00001490 d __DTOR_END__
0000148c d __DTOR_LIST__
00000480 r __FRAME_END__
00001494 d __JCR_END__
00001494 d __JCR_LIST__
00001590 A __bss_start
         w __cxa_finalize@@GLIBC_2.1.3
00000420 t __do_global_ctors_aux
00000360 t __do_global_dtors_aux
00001588 d __dso_handle
         w __gmon_start__
000003f7 t __i686.get_pc_thunk.bx
00001590 A _edata
00001594 A _end
00000454 T _fini
000002f8 T _init
00001590 b completed.5843
000003c0 t frame_dummy
0000158c d p.5841
000003fc T print_name
         U printf@@GLIBC_2.0

Een gedeelde bibliotheek verschilt op een zeer belangrijke manier van een statische bibliotheek: deze sluit zichzelf niet in in uw uiteindelijke uitvoerbare bestand. In plaats daarvan bevat het uitvoerbare bestand een verwijzing naar die gedeelde bibliotheek die is opgelost, niet tijdens het koppelen, maar tijdens runtime. Dit heeft een aantal voordelen:

  • Uw uitvoerbare bestand is veel kleiner. Het bevat alleen de code die u expliciet hebt gekoppeld via de objectbestanden. De externe bibliotheken zijn verwijzingen en hun code gaat niet naar het binaire bestand.
  • U kunt de bits van één bibliotheek (vandaar de naam) delen onder meerdere uitvoerbare bestanden.
  • U kunt, als u voorzichtig bent met binaire compatibiliteit, de code in de bibliotheek bijwerken tussen de programma's en het programma zal de nieuwe bibliotheek ophalen zonder dat u deze hoeft te wijzigen.

Er zijn een aantal nadelen:

  • Het kost tijd om een ​​programma aan elkaar te koppelen. Met gedeelde bibliotheken wordt een deel van deze tijd uitgesteld naar elke keer dat het uitvoerbare bestand wordt uitgevoerd.
  • Het proces is complexer. Alle aanvullende symbolen in de gedeelde bibliotheek maken deel uit van de infrastructuur die nodig is om de bibliotheekverbinding tijdens runtime te maken.
  • U loopt het risico van subtiele incompatibiliteiten tussen verschillende versies van de bibliotheek. In Windows wordt dit "DLL-hel" genoemd.

(Als je erover nadenkt, zijn veel van deze redenen de programma's gebruiken of gebruiken ze geen verwijzingen en verwijzingen in plaats van objecten rechtstreeks in te bedden in andere objecten. De analogie is redelijk direct.)

Ok, dat is veel detail, en ik heb veel overgeslagen, zoals hoe het koppelingsproces werkt. Ik hoop dat je het kunt volgen. Als je niet om opheldering vraagt.


66
2017-07-31 05:55



A .so is analoog aan een .dll voor Windows. A .o is precies hetzelfde als een .obj onder Visual Studio.


2
2017-07-31 05:42