如果速度是重要的并且不需要压缩,你可以连接所使用的系统调用包装tar
使用LD_PRELOAD
,改变tar
计算对我们来说。通过重新实现其中的一些功能,以满足我们的需要(计算潜在产出焦油数据的大小),我们能够消除大量的read
,并write
认为在正常操作中执行tar
。这样可以tar
更快地进行操作,因为它不需要上下文切换到内核附近的任何地方,并且只需stat
要从磁盘读取请求的输入文件/文件夹而不是实际的文件数据即可。
下面的代码包括的实施方式close
,read
和write
POSIX功能。宏OUT_FD
控制我们希望tar
将哪个文件描述符用作输出文件。当前将其设置为stdout。
read
更改为仅返回count
字节的成功值,而不是用数据填充buf,因为未读取实际数据buf不会包含传递给压缩的有效数据,因此,如果使用压缩,我们将计算出错误的值尺寸。
write
更改为将输入count
字节加到全局变量中,total
并仅在文件描述符匹配时返回count
字节的成功值,否则它将调用通过获取的原始包装器以执行相同名称的syscall。OUT_FD
dlsym
close
仍然会执行其所有原始功能,但是如果文件描述符与OUT_FD相匹配,它将知道tar
尝试写入tar文件已完成,因此该total
数字是最终的,并将其打印到stdout。
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <errno.h>
#include <dlfcn.h>
#include <string.h>
#define OUT_FD 1
uint64_t total = 0;
ssize_t (*original_write)(int, const void *, size_t) = NULL;
int (*original_close)(int) = NULL;
void print_total(void)
{
printf("%" PRIu64 "\n", total);
}
int close(int fd)
{
if(! original_close)
{
original_close = dlsym(RTLD_NEXT, "close");
}
if(fd == OUT_FD)
{
print_total();
}
return original_close(fd);
}
ssize_t read(int fd, void *buf, size_t count)
{
return count;
}
ssize_t write(int fd, const void *buf, size_t count)
{
if(!original_write)
{
original_write = dlsym(RTLD_NEXT, "write");
}
if(fd == OUT_FD)
{
total += count;
return count;
}
return original_write(fd, buf, count);
}
基准比较解决方案,其中对解决方案执行了读取磁盘访问和正常tar操作的所有系统调用LD_PRELOAD
。
$ time tar -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/ | wc -c
332308480
real 0m0.457s
user 0m0.064s
sys 0m0.772s
tarsize$ time ./tarsize.sh -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/
332308480
real 0m0.016s
user 0m0.004s
sys 0m0.008s
存储库中提供了以上代码,将上述内容构建为共享库的基本构建脚本以及使用该脚本的“ LD_PRELOAD
技术” 脚本:https :
//github.com/G4Vi/tarsize
有关使用LD_PRELOAD的一些信息:https : //rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/
--totals
选择使用。无论哪种方式,如果您填满磁盘,都可以简单地删除存档,恕我直言。要检查所有可用选项,您可以通过tar --help
。