tail 是否读取整个文件?

tail 是否读取整个文件?

如果我想要tail一个 25 GB 的文本文件,该tail命令会读取整个文件吗?

由于文件可能分散在磁盘上,我想它必须如此,但我不太了解这样的内部结构。

答案1

不,tail不读取整个文件,它会查找到末尾,然后向后读取块,直到达到预期的行数,然后以正确的方向显示行,直到文件末尾,并可能继续监视文件(如果-f使用该选项)。

但请注意,tail如果提供了不可查找的输入,则别无选择,只能读取整个数据,例如从管道读取时。

类似地,当被要求查找从文件开头开始的行时,如果支持使用tail -n +linenumber语法或tail +linenumber非标准选项,tail显然会读取整个文件(除非被中断)。

答案2

您自己可以看到如何tail运作。正如您所见,我的一个文件read被执行了 3 次,总共读取了大约 10K 字节:

strace 2>&1  tail ./huge-file >/dev/null  | grep -e "read" -e "lseek" -e "open" -e "close"
open("./huge-file", O_RDONLY)           = 3
lseek(3, 0, SEEK_CUR)                   = 0
lseek(3, 0, SEEK_END)                   = 80552644
lseek(3, 80551936, SEEK_SET)            = 80551936
read(3, ""..., 708) = 708
lseek(3, 80543744, SEEK_SET)            = 80543744
read(3, ""..., 8192) = 8192
read(3, ""..., 708) = 708
close(3)                                = 0

答案3

由于文件可能分散在磁盘上,我想它必须[顺序读取文件],但我不太了解这样的内部结构。

正如您现在所知,tail只是寻找文件的末尾(使用系统调用lseek),然后向后工作。但在上面引用的评论中,你想知道“tail 如何知道在磁盘上的哪个位置找到文件结尾?”

答案很简单:Tail 不知道。用户级进程将文件视为连续流,因此所有人都tail可以知道距文件开头的偏移量。但在文件系统中,文件的“inode”(目录项)与表示文件数据块的物理位置的数字列表相关联。当您从文件中读取时,内核/设备驱动程序会找出您需要的部分,确定其在磁盘上的位置并为您获取它。

这就是我们操作系统的用途:因此您不必担心文件块分散在哪里。

答案4

正如你在源代码第525行,可以看到实现的注释。

 /* Print the last N_LINES lines from the end of file FD.
   Go backward through the file, reading 'BUFSIZ' bytes at a time (except
   probably the first), until we hit the start of the file or have
   read NUMBER newlines.
   START_POS is the starting position of the read pointer for the file
   associated with FD (may be nonzero).
   END_POS is the file offset of EOF (one larger than offset of last byte).
   Return true if successful.  */

相关内容