/dev/random

Ottimizzare Linux (3)

Accorcio il titolo dei post, perché ormai non si tratta più solo di portatili e server, ma rientrano anche i client. L'argomento di oggi infatti è totalmente trasversale e riguarda tutti gli usi possibili.

Per motivi di efficienza nell'allocazione delle risorse, ogni (buon) programma su Linux si appoggia a una serie più o meno lunga di librerie condivise, le cosiddette Shared Objects, riconoscibili per l'estensione .so

Queste librerie sono gestite in modo da averne in memoria una sola copia in ogni momento, e tutti i software che hanno bisogno delle funzioni fornite leggono dalla stessa copia in memoria. In questo modo si risparmia RAM e tempo di caricamento da disco, in quanto la libreria viene letta da disco una volta sola e poi viene collegata (link) agli eseguibili che ne fanno richiesta.

Ma c'è un problema: ogni programma ha una sua area di memoria isolata dagli altri programmi, e il kernel deve mappare all'interno di ognuna di queste aree le diverse librerie, e ricalcolare tutti gli offset delle funzioni all'interno del binario che le richiama. Questa operazione ha il vantaggio di slegare completamente il binario dalle librerie (possiamo avere due versioni della stessa libreria in memoria con due software diversi che le usano, e caricarli quando vogliamo), ma ha lo svantaggio che, al caricamento del programma, tutte queste mappature devono essere ricalcolate.

Ma c'è, naturalmente, un modo per rendere più efficiente questa operazione.

Prelink

Ed è qui che ci viene in aiuto prelink. Questo software, infatti, analizza tutti i programmi e tutte le librerie che abbiamo installato, e precalcola una volta per tutte degli spazi in memoria dove andranno allocate, quindi modifica i binari stessi per “suggerire” tale allocazione. Può anche spingersi ad analizzare le librerie che non vengono mai usate contemporaneamente e sovrapporre le loro aree di memoria, in modo da ottimizzarne la gestione.

Ma allora perché non lo usano tutti, chiederete voi! Il motivo principale è che ogni volta che si aggiorna qualcosa questo prelinking viene perso, quindi le prestazioni decadono, anche se lentamente. Un altro motivo è che alcuni vecchi software non lo supportano molto bene e rischiano di smettere di funzionare. Per esperienza personale non ne ho ancora incontrato uno, a dire il vero. In ogni caso prelink permette anche l'undo, quindi di ripristinare i binari come erano in origine.

Ma se avete una macchina che non aggiornate troppo spesso (un server, un palmare, ma anche un client, a meno che non usiate Debian sid o non aggiorniate la Debian testing 2-3 volte al giorno), o se siete disposti ad aspettare qualche minuto in più alla fine di ogni aggiornamento, il gioco vale decisamente la candela.

Come usarlo

Se avete una Debian (e, presumo, anche una Ubuntu o altre derivate da Debian), l'installazione e la configurazione sono banali:

aptitude update
aptitude install prelink

vi installerà il pacchetto assieme agli script cron necessari. Controllate il file /etc/default/prelink e, se necessario, modificate la linea che inizia con PRELINKING:

PRELINKING=yes

Nello stesso file ci sono altre opzioni impostabili. Lasciate così com'è la seguente:

PRELINK_OPTS=-mR

mentre, se aggiornate spesso, può essere utile modificare l'intervallo in giorni a cui avviene un “full prelink”:

PRELINK_FULL_TIME_INTERVAL=5

Questo specifica ogni quanti giorni il cronjob farà uno scan completo del sistema per ricalcolare i prelink. In questo caso l'abbiamo impostato a 5 giorni. Potete metterlo a 14 o a 30 se aggiornate molto poco (un server, per esempio), oppure a 1 o 2 se aggiornate ogni giorno.

C'è un ultimo parametro in questo file:

 PRELINK_NONRPM_CHECK_INTERVAL=7

Questo serve a specificare che se non ci sono stati cambiamenti di pacchetti (installazioni o disinstallazioni) negli ultimi 7 giorni, non viene comunque forzato un full prelink, e viene eseguito un prelink incrementale. Funziona analizzando il file di stato della distribuzione, quindi non lasciatevi ingannare da quell'RPM: funziona anche coi deb (se usate il pacchetto deb di prelink, naturalmente).

La configurazione è finita. Tranne la prima riga, che di solito è undefined o no di default, le altre potete anche lasciarle come sono. Non era difficile, no? :)

Avvio del prelink

Ora potete aspettare che cron faccia il suo lavoro (verso le 6 di mattina per il default Debian), o che lo faccia anacron (se spegnete la macchina ogni sera e, naturalmente, avete installato anacron).Oppure potete lanciare l'operazione manualmente richiamando, da utente root, direttamente il cronjob:

/etc/cron.daily/prelink

Undo

Se volete tornare alla situazione di partenza, togliendo tutti i prelink, il comando da dare, sempre da root, è:

prelink -au

Disclaimer

Come ho detto all'inizio, io finora non ho avuto alcun tipo di problema da prelink, e lo uso su una lenny (e prima su una etch, quando era testing) da oltre due anni. Ma, come dicono i ‘mmericani, your mileage may vary: potreste avere qualcosa che non va con prelink, o potrebbe saltarvi la corrente mentre scrive libc.so e impastarvi il sistema (compratevi un UPS!). A vostro rischio e pericolo. Ma la differenza sui tempi di caricamento si vede a occhio nudo, soprattutto su pacchetti grossi come OpenOffice o simili.

 Altre opzioni

La manpage di prelink elenca molte opzioni possibili. Per un uso normale non servono, ma se volete addentrarvi nei meandri del funzionamento del link su Linux, man prelink è vostro amico. L'unica opzione su cui voglio richiamare l'attenzione è -R, che comunque viene impostata di default in Debian, e serve a rendere casuale l'indirizzo di allocazione di ogni libreria. Questo serve ad evitare che un attaccante (un cracker) che abbia un sistema come il vostro possa prevedere a quale locazione di memoria viene installata una certa libreria, rendendogli più facile l'attacco.

In /etc/prelink.conf la Debian preimposta già quali directory controllare e quali tipi di file ignorare durante il prelink. Si può personalizzare questo file nel caso si installino binari in luoghi fuori dalla gestione della distribuzione (per esempio in /usr/local o in /home). La sintassi è molto semplice, se avete letto e capito il man, altrimenti evitate di metterci mano.