Answers:
不,tail
不读取整个文件,它搜索到末尾,然后向后读取块,直到达到预期的行数,然后按正确的方向显示行,直到文件结束,并可能一直监视文件(如果使用了该-f
选项)。
但是请注意,tail
如果提供了不可搜索的输入(例如,从管道读取时),则只能读取整个数据。
同样,当要求查找从文件开头开始的行时,如果使用受支持的tail -n +linenumber
语法或tail +linenumber
非标准选项,则tail
显然会读取整个文件(除非被打断)。
tail +n
将读取整个文件-首先找到所需的换行数,然后输出其余的。
tail
实现都可以执行或正确执行。例如,busybox 1.21.1 tail
在这方面就被打破了。还要注意的是,当行为变化tail
荷兰国际集团标准输入和标准输入哪里是一个普通文件,并在文件中的初始位置是不是在一开始的时候tail
被调用(像{ cat > /dev/null; tail; } < file
)
您可能已经了解了tail
自己的工作方式。您可以为我的其中一个文件read
完成三遍,总共读取大约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
strace
显示tail
运行时系统调用的功能。有关系统调用的一些介绍,您可以在这里阅读en.wikipedia.org/wiki/System_call。简短地-打开-打开一个文件并返回一个句柄(在此示例中为3),lseek
定位您要读取和read
刚刚读取的位置,并且可以看到它返回读取的字节数,
由于文件可能分散在磁盘上,因此我想它必须[按顺序读取文件],但是我对这种内部结构不太了解。
如您现在所知,tail
只需查找文件的末尾(使用系统调用lseek
),然后向后工作。但是在上面引用的评论中,您想知道“ tail如何知道磁盘上的哪个位置来找到文件的末尾?”
答案很简单:尾巴不知道。用户级进程将文件视为连续流,因此所有人都tail
可以知道是从文件开头的偏移量。但是在文件系统中,文件的“ inode”(目录条目)与数字列表相关联,这些数字表示文件的数据块的物理位置。当您从文件中读取时,内核/设备驱动程序会找出您需要的部分,计算出它在磁盘上的位置并为您获取。
我们的操作系统就是这种情况:因此,您不必担心文件块的分散位置。
正如您在源代码行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. */