- Linux offre comandi come free, vmstat, ps e top per controllare l'effettivo utilizzo della memoria e della CPU, distinguendo tra memoria utilizzata, libera e memorizzata nella cache.
- Strumenti come GDB e Valgrind consentono di rilevare errori di segmentazione, perdite di memoria, accessi illegali e variabili non inizializzate nei programmi nativi.
- Negli ambienti .NET Core, la combinazione di dotnet-dump, LLDB e SOS facilita l'analisi approfondita dei dump di memoria sia su Linux che su Windows.
- Un flusso di lavoro diagnostico ordinato che combina metriche di sistema, registri e analisi dei dump riduce drasticamente il tempo necessario per individuare e correggere i problemi di memoria.
Quando qualcosa va storto su un server Linux, la causa spesso risiede nel modo in cui viene utilizzata la memoria e negli strumenti di debug , ma finché non si sa cosa cercare, tutto sembra un caotico miscuglio di numeri e processi. Comprendere cosa succede nella RAM, come si comportano i programmi e come acquisire i dump di memoria è fondamentale per evitare di procedere alla cieca con la risoluzione dei problemi ogni volta che si presenta uno strano errore o un errore di segmentazione.
In questo articolo, esamineremo in modo dettagliato e semplice come ispezionare la memoria, eseguire il debug dei programmi e analizzare i dump in Linux utilizzando comandi di sistema (free, vmstat, /proc/meminfo), debugger come GDB, analizzatori di memoria come Valgrind e utility specifiche per .NET e altri ambienti. L'obiettivo è fornirvi un arsenale pratico per diagnosticare i problemi di memoria e CPU nei server e negli ambienti di sviluppo professionali.
Panoramica: Memoria in Linux e perché non dovresti fissarti sul 100%
Su un server Linux, la RAM funge da memoria di archiviazione veloce per dati e codice che il sistema deve riutilizzare a breve. L'accesso alla RAM è molto più veloce dell'accesso al disco, quindi il kernel sfrutta questa caratteristica per utilizzarla come cache per file, buffer e pagine di memoria che potrebbero essere necessari a breve.
Nel contesto di un server web che esegue Apache o Nginx , o di un server di database come MySQL o MariaDB, sapere quanta memoria viene utilizzata, quanta è libera e quanta è memorizzata nella cache è fondamentale per dimensionare correttamente i servizi e comprendere namespace e cgroup . Infatti, strumenti di ottimizzazione come MySQLTuner utilizzano questi dati (e altre informazioni) per suggerire impostazioni di buffer, cache e connessione.
È importante comprendere un concetto che spesso sorprende all'inizio: la RAM è progettata per essere utilizzata . Un utilizzo del 90% o persino del 100% non è necessariamente un problema; Linux riempie la RAM con la cache del disco per velocizzare il sistema. Ciò che è veramente preoccupante è quando iniziano a verificarsi errori di memoria insufficiente , processi che si arrestano in modo anomalo con un messaggio OOM (Out Of Memory) o servizi che si bloccano, non semplicemente quando il grafico mostra un "utilizzo elevato".
Ha senso passare a un'ottimizzazione aggressiva solo se si nota che il server diventa instabile, lento o interrompe i servizi a causa di un utilizzo eccessivo della memoria, oppure se si prevede un picco di traffico che potrebbe sovraccaricare le risorse attuali.
Comandi di base per ispezionare la memoria in Linux

Il primo passo per risolvere i problemi di memoria è capire la quantità totale di RAM disponibile e come è suddivisa tra memoria utilizzata, memoria libera, cache e swap. Linux offre diverse utility per questo scopo, ognuna con un diverso livello di dettaglio.
comando free: rapida panoramica di RAM e swap
Il comando più comunemente usato per una rapida occhiata è gratuita, soprattutto con il parametro -h Per visualizzare le dimensioni in un formato leggibile: Per ulteriori informazioni sull'interpretazione e l'ottimizzazione di queste metriche, vedere ottimizzare le statistiche della memoria.
free -h
L'output tipico mostra, in poche righe, la memoria totale, utilizzata, libera, condivisa, buffer e cache , sia per la RAM che per lo spazio di swap. Vedrai qualcosa di simile a questo:
buffer condivisi liberi utilizzati totali memorizzati nella cache Mem: 2.0G 1.5G 470M 300M 0B 414M -/+ buffer/cache: 1.1G 885M Swap: 0B 0B 0B
linea -/+ buffers/cache È particolarmente utile perché mostra la memoria effettivamente utilizzata dai processi (esclusi buffer/cache) e la memoria potenzialmente disponibile per nuove applicazioni. Molti vedono poca "memoria libera" nella prima riga e si allarmano, quando in realtà gran parte di essa è semplicemente memorizzata nella cache e può essere riutilizzato senza drammi.
vmstat: memoria attiva, inattiva e metriche di sistema
Quando hai bisogno di informazioni più dettagliate, vmstat fornisce un quadro più tecnico del sistema. Con:
vmstat -s -S M
Otterrai un elenco con la memoria totale, la memoria utilizzata, la memoria libera, la memoria attiva, la memoria inattiva, i buffer, la memoria di swap, ecc. Ad esempio:
2048 M memoria totale 1582 M memoria utilizzata 1124 M memoria attiva 406 M memoria inattiva 465 M memoria libera 0 M memoria buffer 407 M cache di swap 0 M swap totale 0 M swap utilizzato 0 M swap libero
Il concetto di memoria inattiva è interessante: si tratta di memoria considerata in uso ma non associata a processi attivi, quindi, a fini pratici, si comporta come memoria che il sistema può recuperare . Questo aiuta a spiegare perché Linux potrebbe sembrare "occupare tutto lo spazio" ma, in realtà, ha spazio da liberare quando necessario.
/proc/meminfo: i dettagli grezzi del kernel
Se desideri visualizzare tutti i dettagli gestiti dal kernel, puoi sempre consultare il file /proc/meminfo :
cat /proc/meminfo
Questo file include decine di campi relativi alla gestione della memoria interna : memoria totale, memoria libera, buffer, cache, slab, hugepages, memoria disponibile, ecc. È molto utile per strumenti automatizzati e script di monitoraggio, sebbene la sua lettura diretta sia meno intuitiva rispetto a `free` o `vmstat` e richieda una conoscenza approfondita del significato di ciascun campo.
Pannelli di controllo e la loro “realtà parallela”
Se gestisci un server con pannelli di controllo come cPanel, Plesk, VestaCP o Webmin , noterai che in genere visualizzano grafici della memoria utilizzata, libera e in cache tramite un'interfaccia web. Questi dati sono utili, ma tieni presente che vengono aggiornati periodicamente e a volte non riflettono esattamente lo stato in tempo reale. Per una diagnostica approfondita e un'ottimizzazione precisa, è sempre meglio utilizzare il terminale e i suoi comandi nativi.
Debug dei processi e della memoria con strumenti di sistema
Una volta che si conosce la quantità di memoria disponibile e il suo utilizzo generale, il passo successivo è individuare i processi che consumano risorse in modo anomalo e analizzarne il comportamento. È qui che entrano in gioco utility classiche come ps, top, htop, strace e ltrace, oltre a comandi di rete e di disco che aiutano a eliminare i colli di bottiglia.
ps, top e htop: una radiografia dei processi e della CPU
Il comando `ps` visualizza i processi attivi. Combinato con filtri e opzioni di ordinamento, consente di individuare rapidamente cosa sta consumando la CPU.
ps aux --sort=-%cpu | head
Questo strumento mostra i processi ordinati in base alla percentuale di utilizzo della CPU , all'utilizzo della memoria, all'utente e al comando. È ideale come istantanea per identificare il principale responsabile quando il server ha poche risorse; padroneggiare il terminale consente di agire rapidamente.
D'altra parte, `top` e la sua variante più visiva `htop` offrono una visualizzazione in tempo reale dei processi, dell'utilizzo della CPU, dell'utilizzo della memoria, dello stato (R, S, D, ecc.) e del carico medio . Avviando `top` con:
top -o %CPU
Puoi concentrarti sui processi che utilizzano maggiormente la CPU. Oltre ai numeri, è importante cercare degli schemi :
- Processi nello stato R (in esecuzione) che restano bloccati in alto per molto tempo.
- Cambiamenti improvvisi nel carico medio che indicano recenti picchi di carico.
- Assegnazione della CPU in %us, %sy e %wa (tempo utente, tempo di sistema e attesa I/O).
- Se il processo problematico è un servizio di sistema, un utente specifico o un demone.
- Se il consumo è stabile o Sale e scende a scatti., che potrebbe indicare attività in batch o traffico irregolare.
Un valore %wa (I/O wait) molto elevato è un indizio che il collo di bottiglia potrebbe non risiedere nella CPU, bensì nel disco o nel sottosistema di archiviazione.
Revisione dei thread di un processo: top -H
Per le applicazioni multithread (Java, Python, Node, ecc.), non è sufficiente sapere quale processo sta consumando CPU; è necessario vedere quale thread specifico sta andando fuori controllo . Con:
top -H -p PID
Si ottengono i dettagli di ogni thread all'interno del processo. Se uno di essi risulta al 100% e gli altri sono inattivi, è probabile che ci sia un ciclo infinito, un problema di blocco anomalo o una sezione critica mal progettata in quella parte del codice.
Priorità del processo: nice e renice
Se un processo che richiede molte risorse è legittimo, ma si desidera evitare che sovraccarichi il resto del sistema, è possibile regolarne la priorità (niceness) . I comandi `nice` e `renice` consentono di avviare processi con priorità inferiore o di regolare la priorità di un processo esistente, in modo che il kernel assegni loro meno tempo CPU rispetto ad altre attività critiche.
Altri comandi chiave: pidof, kill, strace e ltrace
Quando il sistema è sotto pressione, è utile poter individuare e controllare rapidamente i processi:
- pidof: ottiene il PID di un processo dal suo nome, perfetto per script o interventi rapidi.
- kill: invia segnali ai processi (TERM, KILL, ecc.) per arrestarli in modo ordinato o per interrompere il processo se si sono bloccati.
- straccio: mostra il chiamate di sistema che esegue un processo; ideale per vedere su cosa è bloccato (letture del disco, socket, ecc.).
- tracciaSimile a strace, ma focalizzato su chiamate alle librerie, utile per risolvere i problemi di utilizzo delle API condivise.
Questi strumenti non sono utili solo per individuare perdite di memoria o crash, ma sono anche ampiamente utilizzati nella sicurezza informatica, nell'analisi forense e nel debug di comportamenti binari anomali.
Comandi per file e disco: lsof, df, du, locate
Quando si sospetta che ci sia qualcosa che non va nell'archiviazione (ad esempio, molti file aperti o dischi pieni), entrano in gioco altri comandi:
- lsof: elencare il file aperti da un processo, utile per trovare perdite di descrittori o file che impediscono lo smontaggio di un file system.
- df: mostra il spazio libero su disco per file system, essenziale per escludere il 100% dei dischi che causano guasti a cascata.
- du: calcola il spazio utilizzato dalle directory, molto utile per individuare le cartelle che crescono in modo incontrollato (registri, backup, ecc.).
- individuare: consente di cercare un file in base al nome utilizzando un database indicizzato, più velocemente di find in molte situazioni.
Comandi di rete per la diagnostica: nc, netstat, ab, tcpdump, wireshark, nmap
Spesso, i problemi di prestazioni e di memoria sono accompagnati da colli di bottiglia o attacchi di rete , quindi è una buona idea avere a portata di mano alcuni strumenti di base:
- nc (netcat): un vero e proprio coltellino svizzero delle reti; apre socket, invia e riceve dati, consente test di servizio e persino tunnel improvvisati.
- netstat: mostra le connessioni attive, i socket in ascolto e le statistiche di rete, utili per vedere se ci sono molte connessioni a una porta specifica.
- ab (Apache Benchmark): genera un carico su un server web per misurare i tempi di risposta e il comportamento sotto stress.
- tcpdump e Wireshark: cattura i pacchetti di rete per analizzare il traffico in profondità; tcpdump nella console, Wireshark con interfaccia grafica.
- NmapScanner di porte e servizi, ampiamente utilizzato sia per gli audit di sicurezza che per il controllo superficie di esposizione del server.
GDB: il classico debugger per errori di memoria e crash di runtime
Quando un programma Linux si blocca a causa di un errore di segmentazione o di un altro grave problema, il passo successivo logico è utilizzare un buon debugger. Lo strumento di punta nel mondo GNU è GDB (GNU Debugger) , che permette di esaminare lo stato interno di un programma, interromperlo in qualsiasi punto, visualizzare le variabili e l'utilizzo della memoria e seguire l'esecuzione passo dopo passo.
GDB è stato originariamente progettato per programmi in C e C++, ma è stato esteso ad altri linguaggi come Rust e persino Assembly , e alla gestione dei percorsi delle librerie come LD_LIBRARY_PATH . È fondamentale nello sviluppo, ma anche nella sicurezza informatica, dove viene utilizzato per il reverse engineering, la ricerca di vulnerabilità e lo sviluppo o il debug di exploit.
Avvia GDB ed esegui un programma
Per utilizzare GDB con un eseguibile, si consiglia di compilare il programma con informazioni di debug utilizzando l'opzione -g dal GCC:
gcc -g -Wall programa.c -o programa
Quindi lo avvii con:
gdb programa
All'interno di GDB, il programma non è ancora in esecuzione. Puoi avviarlo con:
- eseguire ilAvvia il programma con tutti gli argomenti che desideri.
- inizia a: uguale a run, ma si ferma all'inizio della funzione
main.
Se hai un eseguibile chiamato, ad esempio, Suma E se vuoi vedere come elabora i suoi argomenti, dovresti andare in GDB e poi usare run 3 5 per avviarlo con quei parametri dal debugger.
Punti di interruzione e punti di osservazione: mettere in pausa il programma dove necessario
I breakpoint sono punti di arresto nel codice sorgente: quando l'esecuzione li raggiunge, il programma si interrompe ed è possibile ispezionarne lo stato interno. In GDB, vengono definiti con il comando :
break lugar
dove "posizione" può essere il nome di una funzione, il numero di riga o file:riga . Un esempio tipico sarebbe:
break main
In questo modo GDB si ferma esattamente quando entra nella funzione main. Quando il programma si ferma in un punto di interruzione, è possibile visualizzare il codice con l (list), controllare le variabili e navigare nello stack delle chiamate.
I watchpoint funzionano in modo diverso: invece di fermarsi in un punto specifico del codice, si fermano quando il valore di una variabile cambia . Sono molto utili per rilevare la corruzione della memoria o modifiche impreviste a strutture critiche senza dover riempire il codice di istruzioni print.
Controllo del flusso preciso: passo, successivo, continua, termina
Una volta che il programma è stato interrotto in corrispondenza di un punto di interruzione, è possibile procedere in diversi modi:
- passo: esegue la riga seguente e immette le funzioni chiamate.
- GENERAZIONE: esegue la riga seguente senza immettere le funzioni (le esegue "tutte in una volta").
- continua: riprende l'esecuzione fino al successivo punto di interruzione o fino alla terminazione del programma.
- finire: continua finché la funzione corrente non ritorna e torna al punto da cui è stata chiamata.
Questo permette di ispezionare il codice sospetto passo dopo passo, senza dover "ingoiare" l'intero programma. Un trucco utile: in GDB, Premendo Invio si ripete l'ultimo comandoideale per realizzare molti next o step seguito da una minore digitazione.
Stack di chiamate e frame: scopri come siamo arrivati fin qui
Per capire perché si è verificato un errore in un determinato punto, è fondamentale vedere quali funzioni sono state chiamate prima di quel punto. La struttura che memorizza queste informazioni è lo stack delle chiamate . GDB offre diversi comandi per gestirlo:
- bt (backtrace): mostra lo stack completo, con l'elenco delle funzioni annidate e i numeri dei frame.
- up: si sposta di un livello in alto nello stack, fino al punto in cui è stata chiamata la funzione corrente.
- giù: scende di un livello, alla funzione che era in esecuzione.
- fr (frame): visualizza il frame corrente o consente di passare a un altro indicandone il numero.
Questo permette di posizionarsi a diversi livelli della chiamata (ad esempio, passando da una funzione interna a main ) e vedere come si presentavano le variabili in ciascun punto.
Interazione con la memoria: set, return, backtrace yx
Uno dei grandi vantaggi di GDB è che permette di leggere e modificare la memoria mentre il programma è fermo. Alcune operazioni utili includono:
- set: modifica il valore di una variabile durante l'esecuzione, ideale per testare scenari senza ricompilare.
- valore di ritorno: forza la funzione corrente a restituire il valore specificato, senza continuare a eseguire il suo codice.
- backtraccia: già visto, per mostrare lo stack delle chiamate corrente.
- x: esamina il contenuto della memoria a partire da un indirizzo, con formati e dimensioni differenti (ad esempio,
x/4xw 0x7fffffffe000per vedere quattro parole in esadecimale).
Con queste opzioni è possibile replicare gli errori, verificare se un input pericoloso causa un overflow o ispezionare strutture dati complesse sullo stack o sull'heap.
Debug post-mortem con core dump
Linux può generare un file core quando un processo si arresta in modo anomalo a causa di un segnale come SIGSEGV. Questo file contiene lo stato completo del processo al momento dell'arresto anomalo: memoria, registri, stack, ecc. Per attivarlo in una sessione, è sufficiente:
ulimit -c unlimited
Per abilitarli in modo più permanente per gli utenti, è possibile modificare il file /etc/security/limits.conf e aggiungere una riga simile a questa:
* soft core unlimited
Quando un programma si blocca, genera un file solitamente chiamato "core" nella directory di lavoro. È possibile analizzarlo con GDB in questo modo:
gdb ejecutable core
Ciò consente di eseguire un'analisi post-mortem quasi come se il programma fosse ancora attivo, ideale quando l'errore non è facilmente riproducibile a richiesta.
Valgrind: a caccia di perdite di memoria ed errori
Per molti problemi di memoria in C/C++ (e linguaggi simili), GDB è insufficiente perché non è progettato per rilevare automaticamente letture illegali, perdite di memoria o utilizzo di memoria non inizializzata . È qui che entra in gioco Valgrind : un sistema di debug e profilazione che emula il processore e monitora ogni accesso alla memoria.
Valgrind include diversi strumenti, ma il più utilizzato è Memcheck , che sostituisce il gestore di memoria standard del C con un proprio, dotato di zone di protezione attorno ai blocchi allocati . Ciò gli consente di rilevare:
- Utilizzo della memoria non inizializzata (variabili che vengono utilizzate prima di assegnare loro un valore).
- Letture/scritti dopo aver fatto il libero (uso dopo la gratuità).
- Accesso fuori dai confini di un blocco di memoria.
- perdite di memoria (malloc senza puntatori liberi, persi, ecc.).
Esempio senza errori: programma "pulito" in Memcheck
Supponiamo di compilare un piccolo programma "hello world" con informazioni di debug:
gcc -Wall -gstabs valgrind_hello_good.c -o valgrind_hello_good
Se lo esegui con Valgrind con:
valgrind --tool=memcheck --leak-check=full -v ./valgrind_hello_good
Si otterrà una traccia in cui, alla fine, il RIEPILOGO ERRORI indica 0 errori e non vengono segnalate perdite di memoria. Ciò conferma che, almeno dal punto di vista di Memcheck, il programma non presenta anomalie di memoria.
Rileva perdite di memoria
Se modifichi il codice per eseguire una malloc senza liberare la memoria (ad esempio, riservando un byte e non liberandolo mai) e lo ricompili:
gcc -Wall -gstabs valgrind_hello_bad.c -o valgrind_hello_bad
durante l'esecuzione:
valgrind --tool=memcheck --leak-check=full -v ./valgrind_hello_bad
Valgrind visualizzerà un HEAP SUMMARY con un valore "in uso all'uscita" diverso da zero, che indica la quantità di memoria non rilasciata. Inoltre, la sezione "persa definitivamente" mostrerà il numero di byte e blocchi persi, insieme alla traccia della chiamata che ha causato la perdita (funzione, file e riga di codice).
Per i casi più complessi, in cui vengono utilizzati filtri, ad esempio, 100 byte in una funzione leak()L'uscita da Valgrind vi indicherà chiaramente la malloc problematico, consentendo l'aggiunta del free corrispondente e verificare successivamente che il riepilogo torni a zero perdite.
Atti illegali e accessi fuori portata
Un altro errore tipico rilevato da Memcheck è la scrittura ad indirizzi non validi , ad esempio la scrittura all'indirizzo di memoria 0 (NULL) o oltre la fine di un array. Se compili un programma che esegue una scrittura illegale:
gcc -gstabs -Wall valgrind_illegal_read_write.c -o valgrind_illegal_read_write
e lo esegui con:
valgrind -v ./valgrind_illegal_read_write
Vedrai messaggi come:
Scrittura non valida di dimensione 4 su 0x80483C4: main (valgrind_illegal_read_write.c:8) L'indirizzo 0x0 non è in stack, malloc o (di recente) liberato
Questo indica con precisione dove si è verificata la scrittura illegale e quanto era estesa, un problema che nelle esecuzioni normali si manifesta solitamente come un semplice "Errore di segmentazione" senza ulteriori indizi.
Variabili non inizializzate e le loro dipendenze di valore
Memcheck ti avvisa anche quando un La decisione di controllo dipende da una variabile non inizializzataSe si compila un programma con una variabile locale che non viene mai inizializzata e viene utilizzata in un if:
gcc -gstabs -Wall valgrind_unitialized.c -o valgrind_unitialized
e lo esegui con:
valgrind -v --track-origins=yes ./valgrind_unitialized
L'output conterrà qualcosa del tipo:
Il salto o lo spostamento condizionale dipendono dai valori non inizializzati in 0x80483F2: main (valgrind_unitialized.c:9) Il valore non inizializzato è stato creato da un'allocazione dello stack in 0x80483EA: main (valgrind_unitialized.c:7)
Il parametro –track-origins=yes aiuta a individuare il punto in cui la variabile non inizializzata è stata creata per la prima volta, velocizzando notevolmente la correzione del codice.
Uso improprio del rilevamento di errori e di libertà nell'heap
Valgrind verifica anche che free viene chiamato solo su puntatori validiSe provi a liberare memoria che non proviene da mallocOppure se fai doppio clic sullo stesso blocco, otterrai messaggi come questo:
Free() / delete / delete[] / realloc() non valido in 0x402B06C: free (...) di 0x8048449: main (valgrind_illegal_free.c:11)
In molti casi ti dice anche l'indirizzo da cui stai chiamando free Si trova subito dopo un blocco già liberato, consentendone l'identificazione errori di calcolo del puntatore o doppi rilasci.
In sintesi, Valgrind è uno strumento essenziale quando si sospettano perdite di memoria, errori di utilizzo di memoria dopo la sua liberazione o corruzione della memoria nei programmi nativi, e il suo utilizzo combinato con GDB fornisce una visione molto potente dello stato interno delle applicazioni.
Core dump e analisi in Linux e Windows
Nelle applicazioni moderne, soprattutto in .NET Core , l'analisi di problemi complessi relativi alla memoria o alle prestazioni spesso comporta l'acquisizione di dump di memoria per un'analisi accurata su un'altra macchina. Questi dump "congelano" lo stato del processo in un punto specifico nel tempo, proprio come un tradizionale core dump.
Analisi dei dump .NET su Linux con dotnet-dump e LLDB
Negli ambienti .NET Core su Linux, uno degli strumenti consigliati è dotnet-dump . Dopo aver acquisito un dump, è possibile iniziare l'analisi con:
dotnet-dump analyze <dump-file>
È importante che l'analisi venga eseguita su una macchina con la stessa architettura e distribuzione Linux dell'ambiente in cui è stato generato il dump. dotnet-dump è pensato per il codice .NET gestito; per analizzare anche il codice nativo (C/C++), è più appropriato utilizzare LLDB insieme all'estensione SOS.
LLDB consente di eseguire il debug sia del codice gestito che di quello nativo e, con l'aiuto di dotnet-sos, è possibile installare l'estensione SOS, che fornisce comandi specifici per .NET. Per caricare correttamente un dump di .NET Core, LLDB e SOS richiedono determinati file binari dall'ambiente in cui è stato creato il dump:
- libmscordaccore.so
- libcoreclr.so
- dotnet (l'host utilizzato per avviare l'applicazione)
Questi file binari possono solitamente essere scaricati utilizzando lo strumento dotnet-symbol . Se si tratta di una build privata o se non sono presenti sul server dei simboli, è sempre possibile copiarli dalla macchina originale. Se i file binari non sono inclusi nel file di dump, è possibile utilizzare il seguente comando in LLDB/SOS:
setclrpath <ruta>per indicare dove si trovano i file binari .NET Core.setsymbolserver -directory <ruta>per specificare la posizione dei simboli.
Una volta ottenuto tutto il necessario, carica il dump in LLDB, specificando l'host dotnet come eseguibile da sottoporre a debug:
lldb --core <dump-file> <host-program>
qui È la strada per lo scarico e Di solito è binario. dotnet, a meno che non si tratti di un'applicazione autonoma, nel qual caso sarebbe l'eseguibile dell'app stessa (senza l'estensione .dll).
All'interno di LLDB, è spesso necessario configurare il server dei simboli corretto con setsymbolserver -ms per utilizzare il server Microsoft, oppure setsymbolserver -directory <ruta> per una directory locale ed esegui loadsymbols per caricare i simboli nativi. Da lì, è possibile utilizzare i consueti comandi SOS per analizzare l'heap gestito, i thread, le eccezioni, ecc.
Analisi del dump Linux da Windows
I dump generati in Linux non si limitano ad essere analizzati sullo stesso sistema; possono essere aperti anche da Windows con strumenti come Visual Studio, WinDbg o dotnet-dump. Le funzionalità variano:
- Di Visual Studio: consente la pulizia delle discariche con una miscela di codice nativo e gestitocon un'interfaccia grafica molto intuitiva. Si consiglia di consultare la guida specifica per Debug dei dump di memoria di Visual Studio.
- WinDbgSupporto avanzato per dump utente, inclusi dump di Linux Con un flusso di lavoro simile a quello di Windows. È necessario utilizzare la versione x64 di WinDbg per i dump da ambienti Linux x64 o Arm64, e la versione x86 per i dump x86.
- dotnet-dump Su Windows: viene utilizzato nello stesso modo di Linux, con
dotnet-dump analyzeRicordatevi di scegliere la versione x64 o x86 dello strumento in base all'architettura del dump.
Diagnosi professionale dell'elevato utilizzo di CPU e memoria
Oltre agli strumenti specifici, la pulizia della memoria in Linux di solito prevede un flusso di lavoro strutturato per evitare azioni casuali. Uno schema pratico per i server è il seguente:
- Guardare top per rilevare modelli e processi di caricamento sospetti.
- Conferma con ps i processi che utilizzano più CPU e memoria.
- Verificare se il consumo è logico (compilazioni, batch, indicizzato) o se presenta comportamenti anomali.
- Analizza i thread con top -H -p PID quando si tratta di processi multi-thread.
- Per esaminare registri di servizio con journalctl o tail.
- Controlla se il problema è realmente correlato alla CPU o nascosto in... I/O del disco utilizzando iostat.
Per determinare se il collo di bottiglia risiede nella CPU o nel disco, il comando `iostat -xz 1 3` è molto utile: se si osservano dischi con un utilizzo elevato e tempi di attesa lunghi, insieme a un valore elevato di `%wa` nel comando `top` , il problema probabilmente non è la CPU ma lo storage.
Applicando questo flusso di lavoro, è più facile diagnosticare casi come:
- Bot o traffico dannoso innescando processi php-fpm e sovraccaricando il server web.
- Un Microservizio Java con un thread in un ciclo infinito consumando un intero nucleo.
- Un processo Python che sembra legato alla CPU ma in realtà è bloccato in attesa del disco in ogni iterazione di un ciclo.
Combinando strumenti di sistema (ps, top, vmstat, free), debugger (GDB, LLDB, dotnet-dump), analizzatori di memoria (Valgrind) e comandi di rete e disco, è possibile creare un metodo di lavoro in cui i problemi di memoria e prestazioni in Linux cessano di essere una scatola nera e diventano qualcosa che, con metodo e pazienza, può essere identificato e corretto con notevole precisione.