2016-01-31 112 views
9

假设我们的目的是在运行Linux的嵌入式设备上创建一个开头有大洞的文件,我们稍后将写入该文件。我们打开文件,获取一个文件描述符并在其上调用lseek来寻找某个已知的位置。之后,当我们想要在查询到的位置写入该文件时,我们将其称为write写入文件中没有零填写Linux Linux

但是,在第一次写入时,由seek创建的空洞将被填满,如果空洞足够大,则此操作可能需要一些时间。在我的应用程序中,没有必要进行这种零初始化,因为这个孔的长度是确切的,我将在稍后填入我的数据。

有没有一种方法可以避免在seek之后调用第一个write调用(即使它涉及修改文件系统驱动程序)?或者,在文件开始之前是否有写入文件的方法(追加到文件的前面)?

回答

6

这可能与您的文件系统有关。在ext2/3/4上,reiser,btrfs,xfs之类的,做你所描述的应该是而不是需要很长时间,因为它们支持所谓的“稀疏文件”(占用底层空间较少的文件存储比文件的大小,因为零的运行没有物理存储)。

您可能会尝试的实验dd以确保这样的话:

$ 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 

在你的文件系统,这可能会失败。如果是这样,并且您需要创建一个稀疏文件,请确定您是否可以使用不同的文件系统。

+0

你说得对。在我的情况下,运行'dd if =/dev/zero of =/mnt/mmc /任何bs = 1k seek = 100000'大约需要10秒钟,结果文件大小为97.7M。文件系统是vfat,不幸的是我不能改变这一点,因为我正在使用SD卡,它应该可以跨多个系统读取。 –

+0

是的,没有一个FAT文件系统支持我知道的任何稀疏文件存储。有可能没有办法确切地得到你所要求的,但也许有一个很好的解决方案,你正试图解决的实际问题。 –

+1

@NebojsaMrmak:看看这个[其他答案](http://stackoverflow.com/a/4396912/865874),HTH。 – rodrigo

-1

您是否试过使用国旗MAP_UNINITIALIZED

+1

根据链接手册页,此标志仅适用于匿名内存,即不是来自文件的内存。 – rodrigo

1

但是,在第一次写入时,由seek创建的空洞将被填满,如果空洞足够大,此操作可能需要一些时间。

不,它不能。它只会将您提供的数据写入write()。未写入部分中的零不是物理存在的:它们是文件系统的人造物。

+0

虽然你的评论是真的,但它确实不是说有没有办法解决这个问题?我正在寻找的是解决这个事实的解决办法。 –

+0

如果我的*答案*为真,那么没有任何行为可以解决。你所问的零字节写法是虚构的。否则我的回答是错误的。你不能两面都有。 – EJP

+1

不准确:并非所有文件系统都支持稀疏文件。 OP正在使用vfat,这肯定没有。 –

0

由于各种原因,这对您的用例可能不是一个可行的解决方案,但我可以想象将大文件拆分为连续编号的块。缺失或零大小的块应该包含零(或其他固定值)。选择块大小以适合您要保留的空间,并在文件大小和块数之间取得妥协。

或者使它更复杂一些,并使用可变块大小,其中个别块的“虚拟”大小存储在其他地方。给定一个足够复杂的编号系统,你甚至可以插入新的数据块不重命名后续块文件...

当然,你需要一个额外的接入层做去分块,无论是在应用程序代码,如果这是足够,或作为内核驱动程序挂钩到文件处理中的最坏情况。