I file vengono aperti da processi caricati nella RAM?


24

I comandi , ad esempio sed, sono programmi e programmi sono logici codificati all'interno di un file e questi file si trovano da qualche parte sul disco rigido. Tuttavia, quando vengono eseguiti i comandi, una copia dei loro file dal disco rigido viene inserita nella RAM , dove prendono vita e possono fare cose e vengono chiamati processi .

I processi possono fare uso di altri file, leggere o scrivere in essi e, se lo fanno, vengono chiamati file aperti. C'è un comando per elencare tutti i file aperti da parte di tutti i processi in esecuzione: lsof.

OK, quindi quello che mi chiedo è se la doppia durata di un comando, uno sul disco rigido, l'altro nella RAM è vero anche per altri tipi di file, ad esempio quelli che non hanno una logica programmata, ma sono semplicemente contenitori per dati.

La mia ipotesi è che i file aperti dai processi vengano caricati anche nella RAM. Non so se sia vero, è solo un'intuizione.

Per favore, qualcuno potrebbe averne un senso?


Risposte:


27

Tuttavia, quando vengono eseguiti i comandi, una copia dei loro file dal disco rigido viene inserita nella RAM,

Questo è sbagliato (in generale). Quando viene eseguito un programma (tramite execve (2) ...) il processo (eseguendo quel programma) sta cambiando il suo spazio di indirizzi virtuale e il kernel sta riconfigurando la MMU a tale scopo. Leggi anche sulla memoria virtuale . Nota che i programmi applicativi possono cambiare il loro spazio di indirizzi virtuale usando mmap (2) e munmap& mprotect (2) , usati anche dal linker dinamico (vedi ld-linux (8) ). Vedi anche madvise (2) e posix_fadvise (2) e mlock (2) .

Errori di pagina futuri verranno elaborati dal kernel per caricare (pigramente) pagine dal file eseguibile. Leggi anche sul thrashing .

Il kernel mantiene una cache di pagine di grandi dimensioni . Leggi anche su copia su scrittura . Vedi anche readahead (2) .

OK, quindi quello che mi chiedo è se la doppia durata di un comando, uno sul disco rigido, l'altro nella RAM è vero anche per altri tipi di file, ad esempio quelli che non hanno una logica programmata, ma sono semplicemente contenitori per dati.

Per le chiamate di sistema come read (2) e write (2) viene utilizzata anche la cache della pagina. Se i dati da leggere si trovano al suo interno, non verrà eseguito alcun IO del disco. Se è necessario l'IO del disco, molto probabilmente i dati letti verrebbero inseriti nella cache della pagina. Quindi, in pratica, se si esegue lo stesso comando due volte, potrebbe accadere che non venga eseguito nessun I / O fisico sul disco per la seconda volta (se si dispone di un vecchio disco rigido rotante, non di un SSD), è possibile udirlo; o osservare attentamente il LED del disco rigido).

Consiglio di leggere un libro come Operating Systems: Three Easy Pieces (scaricabile gratuitamente, un file PDF per capitolo) che spiega tutto questo.

Vedi anche Linux Ate My RAM ed eseguire comandi come xosview, top, htopo cat /proc/self/mapsoppure cat /proc/$$/maps(vedi proc (5) ).

PS. Mi sto concentrando su Linux, ma anche altri sistemi operativi hanno memoria virtuale e cache delle pagine.


35

No, un file non viene letto automaticamente in memoria aprendolo. Sarebbe terribilmente inefficiente. sed, ad esempio, legge il suo input riga per riga, così come molti altri strumenti Unix. Raramente deve conservare più della linea corrente in memoria.

Con awkè lo stesso. Legge un record alla volta, che per impostazione predefinita è una riga. Se memorizzi parti dei dati di input in variabili, questo sarà extra, ovviamente 1 .

Alcune persone hanno l'abitudine di fare cose del genere

for line in $(cat file); do ...; done

Poiché il serbatoio dovrà espandere la $(cat file)completa sostituzione di comando prima di eseguire anche la prima iterazione del forciclo, questo sarà letto per intero filenella memoria (nella memoria utilizzata dalla shell eseguendo il forloop). Questo è un po 'sciocco e anche inelegante. Invece, si dovrebbe fare

while IFS= read -r line; do ...; done <file

Questo elaborerà fileriga per riga (ma leggi Comprensione "IFS = leggi -r riga" ).

L'elaborazione dei file riga per riga nella shell è raramente necessaria, poiché la maggior parte dei programmi di utilità sono comunque orientati alla riga (consultare Perché l'utilizzo di un loop di shell per elaborare il testo è considerato una cattiva pratica? ).

Sto lavorando in bioinformatica e durante l'elaborazione di enormi quantità di dati genomici non sarei in grado di fare molto a meno che non conservassi solo i bit di dati che erano assolutamente necessari in memoria. Ad esempio, quando ho bisogno di rimuovere i bit di dati che potrebbero essere utilizzati per identificare le persone da un set di dati da 1 terabyte contenente varianti di DNA in un file VCF (perché quel tipo di dati non può essere reso pubblico), lo faccio riga per riga elaborazione con un semplice awkprogramma (ciò è possibile poiché il formato VCF è orientato alla linea). Io non leggo il file in memoria, il processo lì, e scrivere di nuovo fuori di nuovo! Se il file fosse compresso, lo farei scorrere zcato gzip -d -c, che, dal momento che gzipesegue lo streaming dei dati, non leggerebbe l'intero file in memoria.

Anche con formati di file che non sono orientati alla linea, come JSON o XML, esistono stream parser che consentono di elaborare file di grandi dimensioni senza archiviarli tutti nella RAM.

Con gli eseguibili, è leggermente più complicato poiché le librerie condivise possono essere caricate su richiesta e / o condivise tra processi (vedere Caricamento delle librerie condivise e utilizzo della RAM , ad esempio).

La memorizzazione nella cache è qualcosa che non ho menzionato qui. Questa è l'azione dell'utilizzo della RAM per contenere pezzi di dati a cui si accede frequentemente. I file più piccoli (ad esempio gli eseguibili) possono essere memorizzati nella cache dal sistema operativo nella speranza che l'utente faccia molti riferimenti ad essi. Oltre alla prima lettura del file, verranno effettuati accessi successivi alla RAM anziché al disco. La memorizzazione nella cache, come il buffering di input e output, è generalmente in gran parte trasparente per l'utente e la quantità di memoria utilizzata per memorizzare nella cache le cose può cambiare in modo dinamico a seconda della quantità di RAM allocata dalle applicazioni ecc.


1 Tecnicamente, la maggior parte dei programmi probabilmente legge un blocco dei dati di input alla volta, usando il buffering esplicito, o implicitamente attraverso il buffering che fanno le librerie I / O standard, e quindi presenta quel blocco riga per riga al codice dell'utente. È molto più efficiente leggere un multiplo della dimensione del blocco del disco rispetto ad esempio a un carattere alla volta. Questa dimensione del pezzo raramente sarà più grande di una manciata di kilobyte però.


hai detto, è possibile caricare librerie condivise nella RAM, è anche possibile caricare un file normale, che contiene solo i dati nella RAM, anche se non avrebbe senso?
Sharkant,

1
@sharkant Certo. È solo questione di aggiungere dati a una variabile (o array, o hash, o qualsiasi altra struttura di dati fornita dalla lingua in questione) fino a quando tutto il file è stato archiviato. Con awk, { a[i++] = $0 }aggiungerebbe tutte le righe del file di input all'array a. Puoi anche cercare la funzione C mmap(), ma il suo uso potrebbe essere un po 'fuori tema qui.
Kusalananda

6
sed, awke altri programmi orientati alla linea non leggono una riga alla volta nella memoria, poiché i file di testo normale non contengono un indice di riga e le API del filesystem e l'hardware di archiviazione di basso livello leggono uno o più "settori" (in genere 512 o 1024 byte) alla volta. Sarei sorpreso se il sistema operativo leggesse meno di 8 KB dal sistema operativo prima dell'elaborazione della prima riga.
Russell Borogove,

5
Sebbene un'utilità come sedleggerà solo una riga alla volta in memoria, vale la pena ricordare che il sistema operativo utilizzerà ram gratis per memorizzare nella cache i file in modo che possano accedervi rapidamente. Se si esegue sedsu un file più piccolo, è possibile che il sistema operativo memorizzi nella cache l'intero file in memoria e l'operazione verrà eseguita interamente nella RAM. Vedi: en.wikipedia.org/wiki/Page_cache
Sean Dawson,

5
@sharkant È utile avere un file interamente accessibile in memoria (vedere l'altra risposta, mmap è la parola chiave chiamata di sistema qui). Ad esempio, un sistema di database di solito vorrebbe avere, per facilità e velocità di accesso, l'intero database o almeno alcuni degli indici mappati in memoria. Questo non significa necessariamente che l'intera cosa sia effettivamente nella memoria. Il sistema operativo è libero di "fingere" che il file sia in memoria. Indica all'applicazione "qui, in questo intervallo di memoria c'è il tuo file", e solo una volta effettuata la lettura (proprio come quando il processo è stato scambiato), i dati vengono effettivamente letti.
Jonas Schäfer,

5

No. Mentre avere concerti di RAM in questi giorni è fantastico, c'è stato un tempo in cui la RAM era una risorsa molto limitata (ho imparato a programmare su un VAX 11/750 con 2 MB di RAM) e l'unica cosa nella RAM era eseguibile attivo e pagine di dati di processi attivi e dati di file presenti nella cache del buffer.
La cache del buffer è stata svuotata e le pagine di dati sono state scambiate. E spesso a volte. Le pagine eseguibili di sola lettura erano sovrascritte e le tabelle delle pagine contrassegnate in modo tale che se il programma avesse toccato nuovamente quelle pagine sarebbero state paginate dal filesystem. I dati sono stati pagati dallo swap. Come notato sopra, la libreria STDIO ha inserito i dati in blocchi e sono stati ottenuti dal programma secondo necessità: fgetc, fgets, fread, ecc. Con mmap, un file può essere mappato nello spazio degli indirizzi di un processo, come ad esempio con oggetti di libreria condivisa o file regolari. Sì, potresti avere un certo controllo se è nella RAM o no (mlock), ma va così lontano (vedi la sezione del codice di errore di mlock).


1
L'affermazione "la tua RAM sarà troppo piccola per i tuoi file" è vera ora come ai vecchi tempi di VAX.
Federico Poloni,

1
@Federico_Poloni Oggi non è così vero. Al mio ultimo datore di lavoro avevamo un PC di classe workstation con 1 TB di RAM e solo 0,5 TB di disco rigido. (Classe del problema: input piccoli, output medi, grandi array a accesso casuale durante il calcolo).
nigel222
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.