Questo è un vecchio post, tuttavia, mi prenderei comunque la libertà di esprimere i miei pensieri qui.
Partendo dal basso, Linux prima dividerebbe la memoria in pagine (di solito 4K per pagina sul sistema x86_64). Successivamente, viene creata la memoria virtuale, la cui mappatura viene eseguita con la memoria fisica utilizzando MMU (Memory Management Unit).
I processi sono allocati in memoria dall'area di memoria virtuale, quindi tieni presente che quando vedi / proc / meminfo, vedrai VMalloc * come i dettagli della memoria virtuale.
Diciamo che hai un processo che richiede memoria (diciamo 300 MB - un browser web). Il processo verrebbe allocato a 300 MB dalla memoria virtuale, tuttavia non è necessario che sia mappato in memoria (che è mappato alla memoria fisica). Esiste il concetto di "Copia su scrittura" per la gestione della memoria, in base al quale, se i processi in realtà utilizzano la memoria allocata dalla memoria virtuale (ovvero fa qualche scrittura sulla memoria), solo allora viene mappato sulla memoria fisica. Questo aiuta il kernel a funzionare correttamente in un ambiente multi-processo in modo efficiente.
Cosa sono i cache?
Molta memoria utilizzata dai processi è condivisa. Supponiamo che la libreria glibc sia utilizzata da quasi tutti i processi. Qual è il punto di conservare più copie di glibc in memoria, quando ogni processo può accedere alla stessa posizione di memoria e svolgere il lavoro. Tali risorse utilizzate di frequente vengono conservate nella cache in modo che, quando richiesto dai processi, possano essere referenziate nella stessa posizione di memoria. Questo aiuta ad accelerare i processi, poiché la lettura ripetuta di glibc (ecc.) Dal disco richiederebbe molto tempo.
Quanto sopra era per le librerie condivise per dire, simile vale anche per la lettura dei file. Se leggi un file di grandi dimensioni (diciamo 100-200 MB) per la prima volta, ci vorrebbe molto tempo. Tuttavia, quando si tenta di ripetere la stessa lettura, sarebbe più veloce. I dati sono stati memorizzati nella cache e la rilettura non è stata eseguita per tutti i blocchi.
Che cos'è il buffer?
Per quanto riguarda il buffer, quando un processo esegue il file I / O, si basa sul buffer del kernel per scrivere i dati sul disco. I processi, richiede al kernel di fare il lavoro. Quindi, per conto del processo, il kernel scrive i dati nel suo "buffer" e dice al processo che la scrittura è stata eseguita. In modo asincrono, il kernel continuerà a sincronizzare questi dati nel buffer su disco. In questo modo, i processi si affidano al kernel per scegliere il momento giusto per sincronizzare i dati su disco e i processi potrebbero continuare a lavorare in anticipo. Ricorda, questo è I / O generale che stanno facendo i normali processi. Tuttavia, i processi specializzati, che devono confermare che l'I / O viene effettivamente eseguito sul disco, possono utilizzare altri meccanismi per eseguire l'I / O sul disco. Alcune delle utility opensource sono libaio. Inoltre, ci sono modi per chiamare la sincronizzazione esplicita con gli FD aperti nel contesto dei processi,
Che cosa sono gli errori di pagina allora?
Considera un esempio, quando avvii un processo (ad esempio un browser Web), il cui binario è di circa 300 MB. Tuttavia, i 300 MB completi del file binario del browser Web non iniziano a funzionare immediatamente. Il processo continua a spostarsi da funzioni a funzioni nel suo codice. Come detto in precedenza, la memoria virtuale sarebbe consumata a 300 MB, tuttavia non tutta la memoria è mappata sulla memoria fisica (la memoria residente RSS sarebbe inferiore, vedere l'output superiore). Quando l'esecuzione del codice raggiunge un punto, per il quale la memoria non è effettivamente mappata fisicamente, si verificherebbe un errore di pagina. Il kernel mapperebbe questa memoria su fisica, associando la pagina di memoria al tuo processo. Tale errore di pagina viene chiamato "Errori di pagina minori". Allo stesso modo, quando un processo sta eseguendo I / O su file, vengono generati errori principali della pagina.
Quando e perché avviene lo Swap Out?
Situazione 1:
In linea con i dettagli sopra, consideriamo uno scenario in cui la buona quantità di memoria viene mappata in memoria. E ora si avvia un processo, che richiede memoria. Come discusso in precedenza, il kernel dovrà eseguire alcune mappature della memoria. Tuttavia, non è disponibile RAM fisica sufficiente per mappare la memoria. Ora, il kernel esaminerà prima nella cache, avrà alcune vecchie pagine di memoria che non vengono utilizzate. Svuota quelle pagine su una partizione separata (chiamata SWAP), libera alcune pagine e mappa le pagine liberate sulla nuova richiesta in arrivo. Poiché la scrittura su disco è molto più lenta della RAM a stato solido, questo processo richiede molto tempo e quindi si osserva un rallentamento.
Situazione 2:
Diciamo che vedi molta memoria libera disponibile nel sistema. Anche allora vedi che stanno avvenendo molti swap-out. Potrebbe esserci un probabile problema di frammentazione della memoria. Si consideri un processo che richiede dal kernel 50 MB di memoria contigua. (tenere a mente contiguo). Ovviamente, il kernel avrebbe assegnato le pagine in modo casuale a processi diversi e ne avrebbe liberato alcuni. Tuttavia, quando richiediamo memoria contigua, dovrà cercare un pezzo che soddisfi la domanda dei processi. Se non è in grado di ottenere tale memoria, dovrà fare uno scambio di alcune vecchie pagine di memoria e quindi allocare quelle contigue. Anche in questi casi si verificherebbe lo swap out. Avviando Kernel versione 2.6 e successive, tali problemi di frammentazione si sono notevolmente ridotti. Tuttavia, se il sistema è in esecuzione da molto tempo, tali problemi potrebbero ancora presentarsi.
Vedi questo esempio ( output vmstat )
2016-10-29 03:55:32 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
2016-10-29 03:55:32 r b swpd free buff cache si so bi bo in cs us sy id wa st
2016-10-30 03:56:04 19 23 2914752 4692144 3344908 12162628 1660 1 8803 12701 4336 37487 14 7 40 38 0
2016-10-30 03:56:34 3 20 2889296 4977580 3345316 12026752 2109 2 8445 14665 4656 36294 12 7 46 34 0
2016-10-30 03:57:04 1 11 3418868 4939716 3347804 11536356 586 4744 2547 9535 3086 24450 6 3 59 33 0 <<<-----
2016-10-30 03:57:34 3 19 3456252 5449884 3348400 11489728 3291 13371 6407 17957 2997 22556 6 4 66 24 0
2016-10-30 03:58:04 7 6 4194500 5663580 3349552 10857424 2407 12240 3824 14560 2295 18237 4 2 65 29 0
2016-10-30 03:58:34 2 16 4203036 5986864 3348908 10838492 4601 16639 7219 18808 2575 21563 6 4 60 31 0
2016-10-30 03:59:04 3 14 4205652 6059196 3348760 10821448 6624 1597 9431 4357 1750 20471 6 2 60 31 0
2016-10-30 03:59:34 2 24 4206968 6053160 3348876 10777216 5221 2067 10106 7377 1731 19161 3 3 62 32 0
2016-10-30 04:00:04 0 13 4205172 6005084 3348932 10785896 6236 1609 10330 6264 1739 20348 4 2 67 26 0
2016-10-30 04:00:34 4 11 4206420 5996396 3348976 10770220 6554 1253 10382 4896 1964 42981 10 5 58 27 0
2016-10-30 04:01:04 6 4 4177176 5878852 3348988 10825840 8682 765 10126 2716 1731 32949 8 4 69 19 0
@ 30-10-2016 03:57:04, vediamo che è ancora disponibile una buona quantità di RAM libera. Tuttavia, anche allora lo scambio è avvenuto. Abbiamo controllato l'albero dei processi a questo punto e non abbiamo visto alcun processo in arrivo che richiederebbe una quantità così elevata di memoria (più della memoria libera). L'ovvio sospetto era la situazione 2 sopra descritta. Abbiamo controllato i registri buddyinfo e zoneinfo sopra (Usa echo m> / proc / sysrq-trigger per controllare questi, l'output va in syslogs).
Per un nostro normale sistema, il confronto delle informazioni sulla zona fa questo. E i grafici per cache / free / low mem sono anche menzionati di seguito
Guardando le informazioni, è chiaro che c'è una frammentazione della memoria nel nodo 0 e nel nodo 1 normale (Nodo è una macchina basata su NUMA, quindi più nodi (vedi numactl per controllare le informazioni per il tuo sistema)).
La frammentazione della memoria è anche un motivo per cui l'utilizzo dello scambio può aumentare anche quando è presente memoria libera.