tail
,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
评论
我看不出这如何回答问题。您能解释一下发生了什么吗?
–伊恩·塞缪尔·麦克莱恩·艾尔德(Iain Samuel McLean Elder)
13年11月29日在15:27
strace显示运行时系统调用tail做的事情。有关系统调用的一些介绍,您可以在这里阅读en.wikipedia.org/wiki/System_call。简要地-打开-打开一个文件并返回一个句柄(在本示例中为3),查找要读取和读取的内容,然后返回所读取的字节数,
–user17530
2013年11月29日15:34
因此,分析系统调用有时可以了解程序的工作方式。
–user17530
13年11月29日在15:41
#3 楼
由于文件可能分散在磁盘上,所以我想它必须[顺序读取文件],但是我对这种内部结构并不了解。
您现在知道,
tail
只是查找到文件的末尾(系统调用lseek
),然后向后工作。但是在上面引用的话中,您想知道“ tail如何知道磁盘上的哪个位置来找到文件的末尾?” 答案很简单:尾巴不知道。用户级进程将文件视为连续的流,因此所有
tail
都可以知道是从文件开头的偏移量。但是在文件系统中,文件的“ inode”(目录条目)与数字列表相关联,这些数字表示文件的数据块的物理位置。当您从文件中读取时,内核/设备驱动程序会找出您需要的部分,计算出它在磁盘上的位置并为您获取。 这就是我们用于操作系统的事情:因此,您不必担心文件块分散在什么地方。
#4 楼
如果head
或tail
似乎正在读取整个文件,则可能的原因是该文件包含很少或没有换行符。几个月前,我用一个很大的(千兆字节)JSON blob进行了绊倒,该序列已被序列化,没有任何空格,甚至没有字符串。如果您有GNU头/尾,则可以使用
-c N
打印前/后N个字节而不是行,但是很遗憾,这不是POSIX功能。#5 楼
正如您在源代码行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. */
评论
该死的,太快了:-)。这是相关的源代码。打印文件FD末尾的最后N_LINES行。向后浏览文件,一次读取“ BUFSIZ”字节(可能第一个除外),直到我们点击文件的开头或已读取NUMBER行。
–干粉
13年11月28日在9:54
另外,tail + n将读取整个文件-首先找到所需的换行数,然后输出其余的换行。
– SF。
13年11月28日在10:20
@SF。确实,答案已更新。
– jlliagre
13年11月28日在10:25
请注意,并非所有的tail实现都可以做到或正确执行。例如,busybox 1.21.1的尾部在这方面就坏了。还要注意,当尾标为stdin且stdin是常规文件并且尾部被调用时文件中的初始位置不在开头时,行为会有所不同(例如{cat> / dev / null; tail;}
–StéphaneChazelas
13年11月28日在10:59
@StephaneChazelas * nix-奇怪的边缘情况的世界变得正常。 (尽管可寻求与不可寻求的输入绝对是正确的观点。)
–用户
13年11月28日在11:49