速度が重要で圧縮が不要な場合は、を使用しtar
て使用するsyscallラッパーをフックしLD_PRELOAD
、変更tar
して計算してください。私たちのニーズに合わせて、これらの機能のいくつかを再実装することにより(電位出力タールデータのサイズを計算する)、我々は多くのを排除することができますread
し、write
それは、通常の操作で行われますtar
。これによりtar
、コンテキストスイッチを前後にカーネルに前後に切り替える必要がなくなりstat
、実際のファイルデータではなく、要求された入力ファイル/フォルダーのみをディスクから読み取る必要があるため、はるかに高速になります。
コードは以下の実装含みclose
、read
およびwrite
POSIX機能を。このマクロOUT_FD
はtar
、出力ファイルとして使用するファイル記述子を制御します。現在、標準出力に設定されています。
read
count
実際のデータが読み取られなかった場合、bufに圧縮を渡すための有効なデータが含まれていないため、bufにデータを入力する代わりに、バイトの成功値を返すように変更されました。サイズ。
write
入力count
バイトをグローバル変数に合計し、ファイル記述子が一致する場合のみバイトtotal
の成功値を返すように変更されました。そうでない場合は、経由で取得した元のラッパーを呼び出して同じ名前のsyscallを実行します。count
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操作のすべてのsyscallsが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
オプションでいろいろ試してみてください。いずれにせよ、ディスクがいっぱいになった場合、アーカイブ、imhoを削除するだけです。利用可能なすべてのオプションを確認するには、を実行できますtar --help
。