2016-01-31 9 views
9

Diciamo che l'intento è quello di creare un file con un buco grande all'inizio che scriveremo più avanti, su un dispositivo embedded su cui è in esecuzione Linux. Apriamo il file, otteniamo un descrittore di file e chiamiamo lseek su di esso per cercare una determinata posizione nota. Successivamente, quando vogliamo scrivere su quel file nella posizione cercata, chiamiamo write su di esso.Scrivi su file senza riempimento zero in Linux

Tuttavia, sul primo scrivere il foro creato dalla ricerca viene riempito a zero e se il foro è abbastanza grande, questa operazione può richiedere del tempo. Nella mia applicazione, non c'è bisogno di questa inizializzazione dello zero, poiché il buco ha una lunghezza esatta e lo riempirò con i miei dati più tardi.

C'è un modo per evitare di avere la prima chiamata write dopo lo seek riempire a zero il foro (anche se ciò comporta la modifica del driver del filesystem)? In alternativa, c'è un modo di scrivere su un file prima dell'inizio del file (che si aggiunge alla parte anteriore del file)?

risposta

6

Questo è probabilmente correlato al tuo filesystem. Su ext2/3/4, reiser, btrfs, xfs e simili, facendo ciò che descrivi dovrebbe non impiegare molto tempo, perché supportano quelli che vengono chiamati "file sparsi" (file che occupano meno spazio nel sottostanti memorizzazione rispetto alla dimensione del file, perché le analisi degli zeri non sono archiviate fisicamente).

Si potrebbe provare un esperimento con dd per assicurarsi che questo è il caso:

$ dd if=/dev/zero of=whatever bs=1k seek=1073741824 count=1 
1+0 records in 
1+0 records out 
1024 bytes (1.0 kB) copied, 9.1878e-05 s, 11.1 MB/s 
$ ls -al whatever 
-rw-r--r-- 1 xxxx xxxx 1099511628800 Jan 31 18:04 whatever 
$ du -h whatever 
16K whatever 

Sul filesystem, che, probabilmente, non riesce. Se è così, e ciò di cui hai bisogno è creare un file sparse, determinare se puoi usare un filesystem differente.

+0

Hai ragione. Nel mio caso, l'esecuzione di 'dd if =/dev/zero di =/mnt/mmc/qualunque bs = 1k seek = 100000' richiede circa 10 secondi e la dimensione del file risultante è 97.7M.Il filesystem è vfat, e sfortunatamente non posso cambiarlo, dal momento che sto operando su una scheda SD, che dovrebbe essere leggibile su più sistemi. –

+0

Sì, nessuno dei file system FAT supporta alcun tipo di archiviazione di file sparse che io conosca. Probabilmente non c'è modo di ottenere esattamente quello che stai chiedendo, ma forse c'è una buona soluzione al problema che stai cercando di risolvere. –

+1

@NebojsaMrmak: dai un'occhiata a questa [altra risposta] (http://stackoverflow.com/a/4396912/865874), HTH. – rodrigo

-1

Hai provato a utilizzare la bandiera MAP_UNINITIALIZED?

+1

In base alla pagina man collegata, questo flag è disponibile solo per la memoria anonima, ovvero la memoria che non proviene da un file. – rodrigo

1

Tuttavia, sul primo scrivere il foro creato dalla ricerca viene riempito a zero e se il foro è abbastanza grande, questa operazione può richiedere del tempo.

No, non è possibile. Scriverà solo i dati forniti a write(). Gli zeri nella parte non scritta non sono fisicamente lì: sono un artefatto del file system.

+0

Mentre il tuo commento è vero, lo fa non dire se c'è un modo per aggirare questo comportamento? Quello che sto cercando è una soluzione a questo fatto. –

+0

Se la mia * risposta * è vera, non ci sono comportamenti da aggirare. Le scritture a zero byte che stai chiedendo sono immaginarie. Oppure la mia risposta è falsa. Non puoi averlo in entrambe le direzioni. – EJP

+1

Inaccurato: non tutti i file system supportano file sparsi. OP sta usando vfat, che sicuramente non funziona. –

0

Questa potrebbe non essere una soluzione fattibile per il vostro caso d'uso per vari motivi, ma posso immaginare di dividere il file di grandi dimensioni in blocchi numerati in serie. Un chunk mancante o zero dovrebbe contenere zero (o qualche altro valore fisso). Scegli la dimensione del blocco per adattarlo allo spazio che desideri riservare e ottenere un buon compromesso tra la dimensione del file e il numero di blocchi.

Oppure renderlo un po 'più complicato e utilizzare dimensioni variabili del blocco, con la dimensione "virtuale" del singolo blocco memorizzato da qualche altra parte. Dato un sistema di numerazione abbastanza complesso puoi persino inserire nuovi blocchi senza rinominare i file chunk successivi ...

Ovviamente avrai bisogno di un ulteriore livello di accesso per eseguire il de-chunking, nel codice dell'applicazione se è sufficiente , o il caso peggiore come driver del kernel che si aggancia alla gestione dei file.