2012-04-03 1 views
5

Se il mio processo sta caricando una libreria .so e se è disponibile una nuova versione della libreria è possibile passare alla nuova libreria senza riavviare un processo? Oppure la risposta dipende da cose come se ci sia un cambio di parametro in una delle funzioni esistenti nella libreria?Aggiorna librerie condivise senza riavviare processi

Sto lavorando in un sistema piuttosto grande che esegue centinaia di processi e ognuno carica 10s di librerie. Le librerie forniscono funzionalità specifiche e sono fornite da team separati. Quindi, quando una delle librerie cambia (per una correzione di bug diciamo) la cosa ideale sarebbe pubblicarla sotto il cofano senza influenzare il processo in esecuzione. È possibile ?

MODIFICA Grazie! Nel mio caso, quando è disponibile una nuova libreria, tutti i processi in esecuzione devono iniziare ad usarlo. La sua non possibilità di lasciarli correre con la vecchia versione e riprendere il nuovo in seguito. Quindi sembra che l'opzione più sicura sia semplicemente ricaricare i processi.

+1

A meno che non si controllino tutti gli eseguibili, aggiornamento a caldo in modo che i file non siano possibili senza hack brutti come i processi di ptracing. Inoltre, linux non usa dll. – BatchyX

risposta

5

Non è possibile aggiornare una libreria collegata al volo con un processo in esecuzione. Si potrebbe anche provare a farlo, ma se si riesce (e non si fallisce con un messaggio di errore "file di testo è in uso"), sarà necessario riavviare il processo per farlo mappare la nuova libreria in memoria.

È possibile utilizzare lsof comando per verificare che le librerie sono collegati in (tempo di esecuzione o LINKTIME):

lsof -p <process_pid> | grep ' mem ' 
+0

Invece di 'lsof -p ', puoi anche usare 'pldd '. – Mikel

+0

pldd: comando non trovato. apt-cache search pldd: nessuno trovato ... – dAm2K

+0

È stato aggiunto a glibc solo a marzo di quest'anno. La tua distribuzione potrebbe non includerla ancora. – Mikel

0

ldd il binario del processo è un modo per scoprirlo. anche se è teoricamente possibile, non è consigliabile armeggiare con il processo in esecuzione, anche se sono sicuro che esistono utility come ksplice che armeggia con i kernel di Linux in esecuzione.

è possibile semplicemente eseguire l'aggiornamento e il processo in esecuzione continuerà con la versione precedente e riprendere la nuova versione al riavvio, presupponendo che il sistema di gestione dei pacchetti sia valido e che sappia quale compatta installare.

0

È possibile conoscere il controllo delle versioni delle librerie condivise e l'opzione ld -h.

Un modo per utilizzarlo è la seguente:

si mantiene un contatore di versione nel vostro sistema di compilazione. Si costruisce la libreria condivisa con:

ld ..... -h mylibrary.so.$VERSION 

tuttavia, lo metti nella lib del vostro albero dev come semplicemente mylibrary.so. (C'è anche un trucco che implica il mettere l'intero file .so in un file .a).

Ora, in fase di esecuzione, i processi che utilizzano la libreria cercano il nome della versione completa. Per implementare una nuova versione, è sufficiente aggiungere alla nuova versione. I programmi in esecuzione collegati alla vecchia versione continuano a usarlo. Quando i programmi vengono ricollegati e testati rispetto a quello nuovo, si rilasciano nuovi eseguibili.

0

A volte si può aggiornare un in-uso .so, e, talvolta, non si può. Questo dipende principalmente da come si prova a farlo, ma anche dalle garanzie di sicurezza del kernel su cui si sta eseguendo.

Non fare questo: gatto new.so> old.so ... perché alla fine, il processo può tentare di chiedere pagina qualcosa, e scoprire che non è nel punto corretto più. È un problema perché gli indirizzi delle cose possono cambiare ed è sempre lo stesso inode; stai solo sovrascrivendo i byte nel file.

Tuttavia, se si: mv new.so old.so Sarete OK sulla maggior parte dei sistemi, perché i processi in esecuzione possono tenere su un inode ora senza nome per la vecchia biblioteca, mentre i nuovi invocazioni dei vostri processi prendi il nuovo file MA, alcuni kernel non amano lasciarti in uso. Così, forse per prudenza, forse per la loro semplicità.

+1

Non penso che "cat new.so> old.so" abbia qualche effetto su un programma in esecuzione. Poiché il kernel sa che il segmento di codice in memoria è mappato alla memoria dove old.so è, rifiuterà di scrivere ("text busy") o addirittura di andare avanti e metterà da parte i settori finché il programma non sarà finito. – SquareRootOfTwentyThree

0

se si prevede libaries a cambiare in maniera abbastanza regolare, e ci si aspetta di mantenere up-tempo, penso che il sistema dovrebbe essere riprogettato in modo che tali librerie effettivamente diventare componenti debolmente accoppiati (ad esempio servizi).

Detto questo, la mia risposta alla domanda è sì: in determinate circostanze, possibile per aggiornare le librerie condivise senza processi riavvio. Nella maggior parte dei casi, non è possibile, , ad esempio quando l'API della libreria cambia, quando la disposizione del segmento di dati cambia, quando la libreria mantiene i thread interni. L'elenco è piuttosto lungo.

Per molto piccole correzioni di bug al codice, si può ancora fare uso di ptrace di scrivere lo spazio di memoria del processo, e da lì rifare ciò che /lib/ld-linux.so fa in termini di dinamica linking. Onestamente, è un'attività estremamente complessa.

3

Una tecnica interessante, sebbene sia in qualche modo soggetta a errori nella fase di ripristino del checkpoint, è quella di eseguire un riavvio invisibile.

Il processo del server o qualsiasi cosa sia, salva tutte le informazioni necessarie nei file del disco. Compresi i numeri dei descrittori di file e gli stati correnti. Quindi, il processo del server esegue una chiamata di sistema exec per eseguire se stessa, sostituendo la versione corrente di se stessa. Quindi legge il suo stato dai file del disco e riprende a servire i suoi descrittori di file come se nulla fosse accaduto.

Se tutto va bene, il riavvio è invisibile e il nuovo processo utilizza tutte le librerie aggiornate.

+1

Un grande esempio è 'irssi' e il suo comando'/upgrade'. –

2

Per lo meno, è necessario assicurarsi che l'interfaccia della libreria non cambi tra le versioni. Se ciò è assicurato, proverei a cercare di caricare dinamicamente le librerie con dlopen/dlsym e vedere se dlclose ti permette di ricaricare.

Non ho mai fatto nulla di tutto ciò, ma questa è la strada da seguire prima. Se vai così, potresti pubblicare i risultati?

2

Linux fornisce diverse interfacce di caricamento dinamico e il processo può caricare librerie dinamiche durante l'esecuzione. dlopen e dlsysm forniti da linux potrebbero risolvere il tuo problema.