在Linux中创建零字节文件的概念是什么?


32

如果我执行以下操作:

touch /tmp/test

然后执行

ls -la /tmp/

我能看到的test文件,0字节的目录。

但是操作系统如何处理0字节的概念。如果我用外行的话来说:

0字节完全没有内存,因此不会创建任何内容。

文件,创建必须应当至少需要一定的内存,对不对?


Answers:


63

文件大致是三个独立的部分:

  • “ inode”,一种元数据结构,可跟踪谁拥有文件,权限以及磁盘上实际包含数据的块列表。
  • 指向该索引节点的一个或多个目录条目(文件名)
  • 实际的数据块本身

创建空文件时,仅创建索引节点和指向该索引节点的目录条目。稀疏文件(dd if=/dev/null of=sparse_file bs=10M seek=1)相同。

当创建到现有文件的硬链接时,只需创建指向相同inode的其他目录条目。

我在这里简化了事情,但您明白了。


2
说得很好。在通过“硬链接”段落提升一个小难题的同时:如果您创建了一个指向空文件的硬链接,而您声明该空文件没有阻止列表,那么该硬链接如何指向(相同)阻止列表哪个不存在?
Theophrastus

4
@Theophrastus好点。我使简化事情成为可能。实际上,在块列表和目录条目之间,存在与文件有关的元数据(称为索引节点编号),并且包含文件属性(所有者,权限等)和扩展属性。块列表在其中。因此,所有目录条目都不直接指向块列表(以FAT方式),而是指向元数据。
xhienne

6
应该是三个独立的事物:包含数据的块列表;街区本身 ; 以及指向块列表的一个或多个目录条目。
通配符

@Wildcard我已经提交了一个编辑,以使其成为三件事,并通过其名称引用了inode。索引节点和目录都是元数据;但是它们是不同类型的元数据。一个文件始终具有一个索引节点和至少一个目录条目。该索引节点可能包括一个空的数据块列表。
Monty Harder

1
@Wildcard即使您是初学者,了解inode和目录之间的区别也很重要。当某人更改“目录名称”的权限/所有权并认为到同一inode的其他链接将保留旧的权限/所有权时,可能发生严重错误。我们不必深入研究inode如何引用直接块,间接块,双重和三重间接块的细节,从而获得一个块列表。或列表可以为空。
蒙迪·哈德

24

touch将创建一个inodels -istat显示有关该inode的信息:

$ touch test
$ ls -i test
28971114 test
$ stat test
  File: ‘test’
  Size: 0           Blocks: 0          IO Block: 4096   regular empty file
Device: fc01h/64513d    Inode: 28971114    Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/1000)   Gid: ( 1000/1000)
Access: 2017-03-28 17:38:07.221131925 +0200
Modify: 2017-03-28 17:38:07.221131925 +0200
Change: 2017-03-28 17:38:07.221131925 +0200
 Birth: -

请注意,它test使用0个块。为了存储显示的数据,inode使用一些字节。这些字节存储在inode表中。在ext2页面上查看inode结构示例


19

ls(或者,stat(2)系统调用)告诉您文件内容的大小。文件系统需要多少空间来记账并不是其中的一部分,并且作为实现细节,程序一般都不应该关心甚至不知道。使实现细节可见将使文件系统抽象的用处不大。


9

文件本身不占用任何空间,但是文件系统却占用文件空间,位置,对文件的访问权限等。


4
如果查看目录条目所占用的空间,则如果目录包含一千个大小为0字节的文件,则该目录将比只有2个大文件的目录条目大。
Mark Stewart

2
提到文件的支持是一个抽象概念,它与它在磁盘上的物理表示没有紧密联系。
Florian Castellane

5

简单的答案:因为是这样定义的。

更长的答案:之所以这样定义是因为某些操作在概念上更简单:

  • 如果文件包含20个字母“ A”,而您删除了所有“ A”,则文件将缩短20个字节。对仅由“ AAAAAAAAAAAAAAAAAAAAAAA”组成的文件执行的相同操作将不得不处理消失文件的特殊情况。
  • 实际上,删除文本文件的最后一行需要特殊情况。
  • 定期进行备份的文本编辑器需要特殊情况的代码,以处理用户可能删除最后一行,吃午饭,然后返回并添加另一行的情况。如果其他一些用户同时创建了具有该名称的文件,则进一步复杂化。

您可以做更多的事情:*错误日志文件倾向于创建为空,仅当发生错误时才被填充。*要找出发生了多少错误,您可以对日志文件中的行数进行计数。如果日志文件为空,则错误数为零,这很合理。*有时,您会在文件名中看到所有相关文本的文件,例如this-is-the-logging-directory。这可以防止急切的管理员在安装后删除空目录,并且还可以防止程序或用户意外创建文件的错误,以便程序以后可以看到目录。该git程序(和其他程序)倾向于忽略空目录,并且如果项目/管理员/用户希望记录该目录,即使该目录没有有用的内容(尚未),您也可能会看到一个名为emptyempty.directory

没有任何操作变得更加复杂:

  • 串联文件:这只是一个空文件的空操作。
  • 在文件中搜索字符串:“如果文件比搜索词短,则它不能包含搜索词”的标准情况涵盖了这一点。
  • 从文件中读取:程序需要在达到期望的值之前先处理文件的末尾,因此,对于文件长度为零的情况,程序员并不需要额外的思考:他只是将文件末尾打到-文件从一开始。

对于文件而言,“在某处记录了文件”方面(索引节点和/或文件名)是上述考虑的基础,但是如果空文件无用,文件系统将不会这样做。

通常,上述所有原因(与文件名有关的原因除外)都适用于序列。最值得注意的是字符串,它是字符序列:零长度字符串在程序内部很常见。如果没有意义,通常在用户级别不允许使用字符串:文件名是字符串,并且大多数文件系统不允许将空字符串作为文件名。在内部,从片段创建文件名时,程序很可能会有一个空字符串作为片段之一。


1

使用最简单的类比:

让我们将文件与一杯水进行比较。

'touch / tmp / test'非常类似于创建一个空杯子,里面没有水。杯子是空的,所以大小为零。但是玻璃确实存在。

用文件系统的话来说,杯子是元数据,而杯子的内容是数据。元数据包含前面帖子中提到的各种内容。

零大小的文件可能很有用。一个示例就是将它们用作面包屑,其中的存在可以用来表示某种状态(即,如果文件存在:则执行某些操作;如果不存在:则忽略)。


0

这样考虑:假设程序正在跟踪发送到服务器的SQL查询。该程序希望表明它正在将请求记录到纯文本文件中,但是尚未记录任何请求。那应该是什么样?我认为它应该是大小为零的文件/var/log/acme-sql-server/queries.log。这样,您就可以确定何时开始记录日志(文件的创建时间),何时最后一次更新文件(即创建文件的时间),记录了多少查询(文件中的换行数= 0)以及谁在进行日志记录(Acme SQL Server)。对于这种情况,有一个空文件的概念仍然存在于特定位置很有用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.