2012-01-15 18 views
15

Supponiamo di avere un'applicazione in Linux che utilizza librerie condivise (file .so). La mia domanda è se il codice in queste librerie alloca memoria nello stesso heap dell'applicazione principale o usa il proprio heap?Le librerie condivise utilizzano lo stesso heap dell'applicazione?

Ad esempio, alcune funzioni nel file .so chiamano malloc, utilizzerebbero lo stesso gestore di heap dell'applicazione o un altro? Inoltre, che dire dei dati globali in quei ricordi condivisi. Dove si trova? So per l'applicazione che si trova nel segmento bss e dati, ma non so dove sia per quei file oggetto condivisi.

+0

Stai chiedendo se le sezioni di una libreria condivisa sono aggregate con le sezioni dell'eseguibile originale con collegamento dinamico? –

+1

I segmenti BSS e Data della libreria condivisa saranno in qualche modo separati dal resto dei segmenti BSS e Dati dell'applicazione, ma tutto ciò è gestito dal sistema per conto dell'utente. –

risposta

25

La mia domanda è se il codice in queste librerie alloca memoria nello stesso heap dell'applicazione principale o utilizza il proprio heap?

Se la libreria utilizza lo stesso malloc/free come l'applicazione (ad esempio, da glibc) - allora sì, il programma e tutte le biblioteche utilizzeranno il singolo mucchio.

Se la libreria utilizza direttamente mmap, può allocare memoria che non è la memoria utilizzata dal programma stesso.

Quindi, ad esempio, alcune funzioni nel file .so chiamano malloc, utilizzerebbero lo stesso gestore di heap dell'applicazione o un altro?

Se funzione da .so chiama malloc, questo malloc è lo stesso di malloc chiamato dal programma. Si può vedere il simbolo di registro vincolante in Linux/glibc (> 2.1) con

LD_DEBUG=bindings ./your_program 

Sì, diversi casi di manager di heap (con configurazione di default) non possono coesistere senza sapere l'uno dell'altro (il problema è con mantenendo sincronizzate le dimensioni heap allocate tra istanze). Ma c'è una configurazione possibile quando più istanze possono coesistere.

maggior parte delle implementazioni malloc classici (ptmalloc *, dlmalloc, ecc) possono utilizzare due metodi di ottenere memoria dal sistema: brk e mmap. Brk è il classico heap, che è lineare e può crescere o restringersi. Mmap consente di ottenere molta memoria ovunque; e puoi restituire questa memoria al sistema (liberandola) in qualsiasi ordine.

Quando malloc viene creato, il metodo brk può essere disabilitato. Quindi malloc emulerà un heap lineare usando solo mmap s o addirittura disabiliterà l'heap lineare classico e tutte le allocazioni verranno eseguite da fragilissimi mmaped fragmens.

Quindi, alcune librerie possono avere un proprio gestore di memoria, ad es. malloc compilato con brk disabilitato o con gestione memoria non-malloc. Questo gestore dovrebbe avere nomi di funzione diversi da e , ad esempio malloc1 e free1 oppure non visualizzare/esportare questi nomi sul linker dinamico.

Inoltre, che dire dei dati globali in quelle memorie condivise. Dove si trova?So per l'applicazione che si trova nel segmento bss e dati, ma non so dove sia per quei file oggetto condivisi.

Si dovrebbe pensare sia al programma che a .so proprio come i file ELF. Ogni file ELF ha "header di programma" (readelf -l elf_file). Il modo in cui i dati vengono caricati da ELF in memoria dipende dal tipo di intestazione del programma. Se il tipo è "LOAD", la parte corrispondente del file sarà privata mmap ed (Sic!) In memoria. Di solito, ci sono 2 segmenti LOAD; il primo per il codice con i flag R + X (leggi + esegui) e il secondo per i dati con flag R + W (leggi + scrivi). Entrambe le sezioni .bss e .data (dati globali) sono posizionate nel segmento di tipo LOAD con flag Abilita scrittura.

Sia la libreria eseguibile che quella condivisa hanno segmenti LOAD. Alcuni segmenti hanno memory_size> file_size. Significa che il segmento verrà espanso nella memoria; prima parte di esso sarà riempito con dati da file ELF, e la seconda parte di dimensioni (memory_size-file_size) saranno riempiti con zero (per *bss sezioni), utilizzando mmap(/dev/zero) e memset(0)

Quando Kernel o carichi linker dinamico ELF archiviare in memoria, non penseranno alla condivisione. Ad esempio, si desidera avviare lo stesso programma due volte. Il primo processo caricherà la parte di sola lettura del file ELF con mmap; il secondo processo farà lo stesso mmap (se aslr è attivo - il secondo mmap sarà in un altro indirizzo virtuale). È compito di Page cache (sottosistema VFS) mantenere una singola copia di dati nella memoria fisica (con COPY-on-WRITE aka COW); e mmap installerà semplicemente i mapping dall'indirizzo virtuale in ogni processo in un'unica posizione fisica. Se qualche processo cambierà una pagina di memoria; sarà copiato in scrittura su una memoria fisica privata univoca.

codice di carico è in glibc/elf/dl-load.c (_dl_map_object_from_fd) per ld.so e linux-kernel/fs/binfmt_elf.c per loader ELF del kernel (elf_map, load_elf_binary). Fare una ricerca per PT_LOAD.

Quindi, i dati globali e i dati bss vengono sempre salvati in privato in ogni processo e sono protetti con COW.

Heap e stack vengono allocati in fase di esecuzione con brk + mmap (heap) e dal kernel del sistema operativo automaticamente in processo di tipo brk (per stack di thread principale). Stack aggiuntivi del thread sono allocati con mmap in pthread_create.

+0

Grazie, la tua risposta è stata molto utile. – MetallicPriest

+0

MetallicPriest, in quale parte è stato più utile? – osgx

+0

osgx - Il secondo è stato più utile. – MetallicPriest

8

Le tabelle dei simboli sono condivise in un intero processo in Linux. malloc() per qualsiasi parte del processo è uguale a tutte le altre parti. Quindi sì, se tutte le parti di un processo accedono allo heap tramite malloc() e quindi condivideranno lo stesso heap.

+0

+1 Potremmo menzionare chiamando brk fuori dal contesto di malloc e le conseguenze di ciò. È possibile avere parti del codice della libreria e del codice locale che non "conoscono" i limiti heap esistenti. Una specie di mucchio schizofrenico. Non bene. –

+0

Il malloc può allocare memoria tramite 'brk' e' mmap'. Solo una singola istanza della libreria malloc può gestire la memoria con brk; ma se c'è un'altra istanza di malloc collegata, può usare mmap per emulare un heap separato. – osgx

Problemi correlati