参考 Unix 环境中的高级编程,当我们尝试查找文件末尾并在那里写入内容时,就会创建文件漏洞。例如,
int x = lseek(fd,1639,SEEK_END);
int y = write(fd,buff,100);
如果考虑上面的示例并假设该文件以前有一些内容,则当前文件偏移量位于文件开头之前的某个位置。现在,我们使用该函数查找文件末尾lseek
(如上例所示),并写入一个缓冲区浅黄色文件大小为 100。如您所知,文件中将创建一个洞。
那么,Unix 可以将此漏洞分配给其他文件吗?或者,换句话说,这个洞是否可以分配?
答案1
首先,什么是文件中的漏洞?它只是将数据设置为零,而没有明确地这样写。当您seek
超出文件末尾 1639 个字节并向其中写入 100 个字节时,您的文件实际上增长了 1639+100 个字节。因此,您创建了一个洞,但该洞实际上是用零填充的。
如果该漏洞足够大,某些文件系统(例如ext
)允许您通过不在磁盘上分配相应的块来节省该空间。即,如果您seek
要写入一个或多个零块,则这些块不会在磁盘上分配,这将在包含文件数据的块列表中创建真正的漏洞。这就是我们所说的稀疏文件。
块的大小取决于 FS 的格式化方式。现在ext
通常是 4096 字节。这意味着,通过 1639 字节查找,您不会创建稀疏文件,并且 1639 个零只会写入磁盘上。 OTOH,对于 4096 字节块,如果您寻求至少 8191 (2 * 4096 - 1) 字节,则可以确定至少创建一个。
由于块实际上并未分配并用零填充,这使得您的文件使用更少的磁盘空间,并且您的写入操作速度更快。当然,为了回答您的问题,空闲的磁盘空间可用于其他文件。
实际上,最好的演示并不需要 C 程序:
$ df -h /tmp
Filesystem Size Used Avail Use% Mounted on
/dev/sda4 38G 28G 7.5G 80% /
$ time dd of=/tmp/foo bs=1M seek=$((1024*1024*10)) count=0
0+0 records in
0+0 records out
0 bytes (0 B) copied, 4.741e-05 s, 0.0 kB/s
real 0m0.002s
user 0m0.000s
sys 0m0.000s
$ ls -lh /tmp/foo
-rw-r--r-- 1 xhienne xhienne 10T Aug 25 20:08 /tmp/foo
$ df -h /tmp
Filesystem Size Used Avail Use% Mounted on
/dev/sda4 38G 28G 7.5G 80% /
在这里,我在几毫秒内在一个只有 7+ GB 可用空间(仍然可用)的分区上创建了一个 10 TB 文件(全是零)。