tar如何读取文件来创建存档?

时间:2013-12-30 23:26:30

标签: linux tar

tar使用什么系统调用来获取用于创建存档的文件内容?我尝试使用strace来查看调用,但它从不在文件上调用open

$ echo "HelloWorld" > my_test_file 
$ strace -s250 -f -F tar -cf /dev/null my_test_file 2>&1 | grep my_test_file
execve("/bin/tar", ["tar", "-cf", "/dev/null", "my_test_file"], [/* 20 vars */]) = 0
newfstatat(AT_FDCWD, "my_test_file", {st_mode=S_IFREG|0664, st_size=11, ...}, AT_SYMLINK_NOFOLLOW) = 0
newfstatat(AT_FDCWD, "my_test_file", {st_mode=S_IFREG|0664, st_size=11, ...}, AT_SYMLINK_NOFOLLOW) = 0

我猜测newfstatat与fstatat几乎完全相同(除了一些细微的差别之外,它“以与stat完全相同的方式运行”),因此可能不会打开文件。

我的tar版本:

$ tar --version
tar (GNU tar) 1.26
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by John Gilmore and Jay Fenlason.

我的操作系统:

$ uname -a 
Linux myhostname 3.11.0-14-generic #21-Ubuntu SMP Tue Nov 12 17:04:55 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=13.10
DISTRIB_CODENAME=saucy
DISTRIB_DESCRIPTION="Ubuntu 13.10"

2 个答案:

答案 0 :(得分:2)

显然,当您tar文件时,必须由运行tar的进程读取。这正是我系统上发生的事情。我从/dev/urandom创建了一个512字节的文件并运行tar -cf file.tar file.xyz。将与加载库相关的所有噪音过滤到流程图像后,您可以看到strace报告的实际相关行:

creat("file.tar", 0666)                 = 3

我们可以看到tar命令的输出文件是使用所有者,组和世界的读/写权限创建的(可能受shell报告的umask影响),以及此过程中新文件的描述符为3。

openat(AT_FDCWD, "file.xyz", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC) = 4

此处,将打开要归档的文件并为其分配文件描述符4.

fstat(4, {st_mode=S_IFREG|0644, st_size=512, ...}) = 0

tar在打开的文件描述符上调用fstat,以便查明文件是否可读及其大小(可能)。

read(4, "\225\243\263uG\320-\354!%\337\3376\311\210&\377T=aiO\10\203\375|y\304\231\203x."..., 512) = 512

我们可以看到实际读取的文件。

close(4)                                = 0

并妥善关闭。

write(3, "file.xyz\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 10240) = 10240

描述符3引用的文件 - 我们的输出文件 - 正在写入。我们无法在file.xyz调用中看到write的内容,但这可能是因为tar文件的结构。

close(3)                                = 0

现在,输出文件以及整个过程(此处未显示)已关闭。

有趣的是,我首先使用touch创建了一个空文件,然后尝试tar它。但是,似乎tar检查文件是否为空,如果是,则不会将数据插入tar存档中。 newfstatat会返回有关大小的信息,tar可能会用来做出此决定。

但是,您应该真正阅读源代码以了解实际执行情况。例如,可能会将更大的文件mmap加入到流程中,并以这种方式读取,而较小的文件只需使用read读取。

答案 1 :(得分:1)

对我而言,在写入/dev/null时以及大小为零时,似乎没有读取源文件。

cd /tmp; echo test > testinput; diff -u <(strace -s250 -f tar -cf /dev/null testinput 2>&1) <(strace -s250 -f tar -cf testoutput testinput 2>&1) | less +'/open\("testinput"'

当输出不是/dev/null并且输入文件不为空时,在输入文件上使用Open。使用GNU tar 1.20和strace 4.5.17。