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"
答案 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。