Guida al Prelink in Gentoo Linux
1.
Introduzione
Cos'è il prelink e come può essermi d'aiuto?
Le più comuni applicazioni utilizzano librerie condivise. Queste librerie
condivise devono essere caricate in memoria durante l'esecuzione ed i vari
simboli e riferimenti devono essere risolti. Per la maggior parte dei piccoli
programmi tale linking dinamico è molto veloce, ma per i programmi scritti in
C++ che dipendono da molte librerie, il linking dinamico può richiedere una
discreta quantità di tempo.
Nella maggior parte dei sistemi le librerie non vengono modificate molto spesso
e, quando un programma è avviato, le operazioni effettuate per il linking sono
sempre le stesse. Il prelink sfrutta questa particolarità estraendo le
informazioni relative al linking e memorizzandole nell'eseguibile,
prelinkandolo, appunto.
Il prelinking può accorciare il tempo di apertura delle applicazioni. Ad
esempio, il tempo di caricamento di un qualsiasi programma KDE può essere
abbreviato fino al 50%. Le uniche operazioni di manutenzione richieste prevedono
di lanciare prelink ogni volta che una libreria di un eseguibile prelinkato
viene aggiornata.
Avvertenza:
Prelink non funzionerà con Gentoo Hardened. Questo avviene perchè entrambi i
progetti tentano di cambiare la mappatura dello spazio di indirizzamento delle
librerie condivise. Tuttavia prelink, tramite l'opzione -R, rende casuale gli
indirizzi di base delle librerie, fornendo un livello minimo di blindatura e
protezione.
|
In breve
-
Il prelinking viene effettuato attraverso un programma chiamato,
sorprendentemente, prelink, che modifica gli eseguibili per farli
partire più velocemente.
-
Se una libreria da cui dipende un'applicazione viene modificata dopo il
prelink, è necessario prelinkare nuovamente l'eseguibile, altrimenti si
perdono i vantaggi in termini di prestazioni. In altre parole, ogni volta
che viene aggiornato con portage un pacchetto che aggiorna delle librerie, è
necessario effettuare nuovamente il prelink.
-
I cambiamenti agli eseguibili sono completamente reversibili. prelink
ha una funzione di "undo" (annullamento dei cambiamenti, ndt).
-
Le versione corrente di Portage tratta correttamente, attraverso
prelink, i cambiamenti di MD5sum e mtime degli eseguibili.
-
Non è necessario impostare FEATURES="prelink" in
make.conf: Portage si appoggerà automaticamente a prelink se
troverà il file binario 'prelinkato'.
2.
Impostare il Prelink
Installare i programmi
Per iniziare è necessario installare prelink. Durante l'esecuzione,
emerge verifica automaticamente che prelink sia supportato dal proprio sistema.
Codice 2.1: Installazione di prelink |
# emerge prelink
|
Molte persone hanno problemi effettuando l'emerge di prelink perché i test
effettuati falliscono. I test sono stati inseriti per motivi di sicurezza e il
comportamento di prelink è imprevedibile se vengono disabilitati. Gli errori di
emerge sono di solito relativi a pacchetti fondamentali come binutils, gcc e
glibc. Provare ad effettuare l'emerge di questi pacchetti in tale ordine.
Nota:
Consiglio: Se si ottengono degli errori provare a compilare e testare
prelink manualmente (./configure ; make ; make check
). In caso di problemi consultare i file *.log nella directory testsuite, che
potrebbero fornire alcuni utili suggerimenti.
|
Se si può riprodurre passo passo un errore di emerge su un altro sistema
controllare Bugzilla e creare un
nuovo bug report, nel caso non ce ne fossero di già esistenti.
Preparare il sistema
Assicurarsi anche di non avere -fPIC nelle CFLAGS/CXXFLAGS. Se così
fosse, bisognerà togliere -fPIC e ricompilare l'intero sistema.
Configurazione
L'esecuzione di env-update genera il file /etc/prelink.conf
da cui prelink rileva i file da prelinkare.
Codice 2.2: Eseguire env-update |
# env-update
|
Purtroppo non è possibile abilitare il prelink per file compilati con vecchie
versioni di binutils. La maggior parte di queste applicazioni proviene da
pacchetti precompilati o binary-only, che sono installati in /opt.
Creando il seguente file è possibile evitare che prelink tenti di prelinkarli.
Codice 2.3: /etc/env.d/60prelink |
PRELINK_PATH_MASK="/opt"
|
Nota:
È possibile aggiungere altre directory separandole con i due punti (:).
|
3.
Prelinking
Utilizzo di prelink
L'autore di queesto documento utilizza il seguente comando per prelinkare tutti
gli eseguibili nelle directory elencate da /etc/prelink.conf.
Codice 3.1: Prelink dei file elencati |
# prelink -amR
|
Avvertenza:
È stato osservato che se si dispone di poco spazio libero su disco e si prelinka
l'intero sistema è possibile che gli eseguibili vengano troncati. Il risultato
finale è un sistema corrotto. Utilizzare i comandi file o readelf
per verificare lo stato dei file binari. In alternativa, controllare lo spazio
libero su disco con df -h prima di procedere.
|
| La spiegazione delle opzioni: |
| -a |
"All": prelinka tutti i binari. |
| -m |
Conserva lo spazio in memoria virtuale. È necessario se ci sono molte
librerie che hanno bisogno di essere prelinkate.
|
| -R |
Random -- rende casuale l'ordinamento degli indirizzi, in modo da aumentare
la sicurezza verso i buffer overflow.
|
Nota:
Per maggiori opzioni e gli altri dettagli, utilizzare man prelink.
|
Prelink Cron Job
sys-devel/prelink-20060213 e successivi installano un cron job in
/etc/cron.daily/prelink. Per abilitarlo, modificare il file di
configurazione /etc/conf.d/prelink. Questo farà eseguire prelink
giornalmente in background, facendo risparmiare all'utente il tempo di doverlo
eseguire manualmente.
Incrementare le Prestazioni di KDE dopo il Prelinking
Dopo il prelinking è possibile ridurre il tempo di caricamento di KDE. Se KDE
rileva di essere stato prelinkato allora disabiliterà il caricamento di
kdeinit (visto che non è più necessario) con un incremento delle sue
prestazioni.
Per fare in modo che KDE rilevi il prelinking impostare
KDE_IS_PRELINKED=1 in /etc/env.d/*kdepaths*.
Rimuovere prelink
Se si cambia idea riguardo all'uso di prelink, prima di disinstallarlo bisogna
prima rimuovere il cronjob di prelink da /etc/cron.daily e
/etc/conf.d/prelink. Successivamente bisogna rimuovere il prelink
da tutti i binari:
Codice 3.2: Rimuovere il prelink da tutti i binari |
# prelink -au
|
Come ultima cosa, disinstallare il pacchetto prelink stesso:
Codice 3.3: Disinstallare prelink |
# emerge -aC prelink
|
4.
Problemi Noti e Soluzioni
"Impossibile prelinkare con librerie condivise non-PIC"
La causa di questo problema è l'errata compilazione di librerie condivise, senza
l'opzione -fPIC di gcc per tutti i relativi file oggetto.
Qui ci sono le librerie che non sono state corrette o non possono essere
corrette:
-
Le librerie nel pacchetto wine, incluso winex. Il prelinking non
velocizzerebbe comunque gli eseguibili MS Windows.
-
Le librerie in media-video/mjpegtools,
/usr/lib/liblavfile-1.6.so.0.
-
Le librerie OpenGl Nvidia,
/usr/lib/opengl/nvidia/lib/libGL.so.*. A causa di problemi
prestazionali, saranno compilare senza il supporto a PIC.
Se le librerie che danno problemi non sono elencate, segnalarle tramite un bug
report su Bugzilla ed allegare, preferibilmente, una patch per aggiungere
-fPIC alle relative CFLAGS.
Quando prelinko il mio sistema alcuni binari statici non funzionano
più
Quando si ha a che fare con le glibc, non si ottiene mai un binario statico al
100%. Anche se si compila staticamente un binario con glibc, potrebbe ancora
dipendere da altri file di sistema. Ecco una spiegazione di Dick Howell,
"Generalmente si presuppone che tutto il necessario sia contenuto nel file
scaricato, in modo che l'applicazione non dipenda da librerie installate sul
sistema locale. Sfortunatamente in Linux, e credo in qualsiasi altro sistema usi
le glibc, ciò non è del tutto vero. Ad esempio "libnss" (name service switch,
chiamata da alcuni network security system), che fornisce delle funzioni per
accedere a diversi database per l'autenticazione, informazioni di rete ed altro,
dovrebbe creare applicazioni indipendenti dall'effettivo ambiente di rete di una
macchina. Una bella idea, ma modifiche alle glibc possono generare problemi nel
tentativo di caricarla. E non è possibile linkare staticamente "libnss", poiché
è configurata per ogni macchina individualmente. Credo che il problema derivi
principalmente dal linkare staticamente altre librerie glibc, in particolare
"libpthread", "libm" e "libc", da cui provengono chiamate incompatibili a
funzioni di "libnss"."
Prelink si blocca con l'errore "prelink: dso.c:306: fdopen_dso:
Assertion `j == k' failed."
Questo problema è noto e ben documentato qui. Prelink non
funziona con eseguibili compressi in formato UPX. Per ora (prelink-20021213) non
esiste alcuna soluzione eccetto quella di nascondere a prelink gli eseguibili in
questione. Leggi la sezione Configurazione
per sapere come farlo facilmente.
Uso grsecurity e sembra che il prelinking non funzioni.
Per prelinkare su un sistema con grsecurity che utilizza chiamate mmap() casuali
è necessario disattivare "randomized mmap() base" per
/lib/ld-2.3.*.so. Per fare ciò, utilizzare il tool chpax
quando tali file non sono in uso (ad esempio, facendo il boot da un CD di
ripristino).
Prelink fallisce con l'errore "prelink: Can't walk directory tree XXXX: Too many
levels of symbolic links"
I propri link simbolici sono annidati troppo in profondità. Questo succede
quando un link simbolico punta a sè stesso. Per esempio, /usr/lib/lib
-> lib è il più comune. Per risolvere il problema, bisogna trovare
manualmente il collegamento simbolico o usare lo strumento fornito dal pacchetto
symlinks:
Codice 4.1: Correggere i collegamenti simbolici |
# emerge symlinks
# symlinks -drv /
|
Ulteriori dettagli si trovano in Bugzilla e in
questa
discussione del forum.
5.
Conclusioni
Il prelinking può velocizzare notevolmente il tempo di avvio di numerose
applicazioni complesse e portage supporta nativamente questa tecnologia. Inoltre
il prelinking è sicuro, perché è sempre possibile annullarlo per i binari che
presentano problemi. Ricordarsi che, se le glibc o altre librerie prelinkate
vengono aggiornate, è necessario eseguire nuovamente prelink! Buona
fortuna!
I contenuti di questo documento sono rilasciati sotto la licenza Creative
Commons - Attribution / Share Alike.
|