假设我们的目的是在运行Linux的嵌入式设备上创建一个开头有大洞的文件。我们打开文件,获取文件描述符并在其上调用lseek
以寻找某个已知位置。之后,当我们想要在搜索到的位置写入该文件时,我们会在其上调用write
。
但是,在第一次写入时,通过搜索创建的孔变为零填充,如果孔足够大,则此操作可能需要一些时间。在我的应用程序中,没有必要进行零初始化,因为这个孔的长度非常精确,我稍后会用我的数据填充它。
有没有办法避免在write
填空之后进行第一次seek
调用(即使它涉及修改文件系统驱动程序)?或者,有没有办法在文件开头之前写入文件(附加到文件的前面)?
答案 0 :(得分:8)
这可能与您的文件系统有关。在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
在您的文件系统上,这可能会失败。如果是这样,您需要创建一个稀疏文件,确定是否可以使用不同的文件系统。
答案 1 :(得分:1)
然而,在第一次写入时,通过搜索创建的孔变为零填充,如果孔足够大,此操作可能需要一些时间。
不,不能。它只会将您提供的数据写入write()
。未写入部分中的零在物理上不存在:它们是文件系统的人工制品。
答案 2 :(得分:0)
由于各种原因,这对于您的用例可能不是一个可行的解决方案,但我可以想象将大文件拆分为连续编号的块。丢失或零大小的块应该包含零(或一些其他固定值)。选择块大小以适合您要保留的空间,并在文件大小和块数之间做出妥协。
或者使它变得更复杂并使用变量块大小,使用"虚拟"存储在其他地方的单个块的大小。给定一个复杂的编号系统,您甚至可以插入新的块而无需重命名后续的块文件...
当然,您需要一个额外的访问层来进行去块,无论是在您的应用程序代码中,还是在内存驱动程序挂钩到文件处理中的最坏情况。
答案 3 :(得分:-1)
您是否尝试使用标记MAP_UNINITIALIZED?