0

ツリー ウォーキングを行うために nftw システム コールを使用する小さなコードを書きました。

int flags =0;
flags = flags | FTW_MOUNT;
int nopenfd = 10;

if( nftw( argv[1], sum_sizes, nopenfd, flags) == -1 )
  return EXIT_FAILURE;

このオプションを使用すると、nftw はディレクトリがマウント ポイントである場合にディレクトリをスキャンせず、シンボリック リンクを逆参照します (デフォルトの動作)。

各ファイル nftw で、次の関数を呼び出します。

/*total_size is the sum of each file/directory/link*/
long long int total_size, total_real_size = 0;

static int sum_sizes(const char *pathname, const struct stat *statbuf, int typeflag, struct FTW *ftwbuf)
{
/*if stat failed on the current file*/
if(typeflag == FTW_NS)
{
    printf("No stats (permissions ?) on %s", pathname);
    return 0;
}
total_size = total_size + (long long int ) statbuf->st_size;
total_real_size = total_real_size + (long long int ) ( statbuf->st_blocks * 512 );
return 0;
}

最後に、累積サイズを表示します。

printf("total size: %lld (%0.2lf K %0.2lf M)\n", total_size,  (float)total_size /1024.0, (float)total_size /(1024.0*1024.0));
printf("total real size: %lld (%0.2lf K %0.2lf M)\n", total_real_size,  (float)total_real_size /1024.0, (float)total_real_size /(1024.0*1024.0));

値を du と比較すると、いくつかの違いがあります

time ./scan_dir ~/        
====>
total size: 15208413390 (14851966.00 K 14503.87 M)
total real size: 15708553216 (15340384.00 K 14980.84 M)
block size : 4096 / fond. block size : 4096
fs size: 22.7895 G
./scan_dir ~/  0,03s user 0,24s system 98% cpu 0,277 total


time du -s ~/     
15119876    /home/cedlemo/
du -s ~/  0,07s user 0,22s system 98% cpu 0,287 total

注: du のマニュアル ページを読んだ後、du は私の小さなアプリケーション scan_dir とほぼ同じ動作をすることがわかりました (マウント ポイントをスキップし、シンボリック リンクを参照解除し、Ko の値を計算するために 1024 を使用します)。

私のアプリケーションで見つかったより近い値は、実際のサイズ (使用されているブロック) の合計のようですが、値は実際には同じではありません。

この違いの理由は何ですか? 私が間違っていることは何ですか?

4

1 に答える 1

1

デフォルトでは、シンボリック リンクをたどりduません。あなたのコードはそうです。

du -ks DIRECTORY/

と同等です

find DIRECTORY/ -printf '%k\n' | awk '{s+=$1} END { printf "%.0f\n", s }'

これは、各ディレクトリ エントリを 1 回だけ参照し、シンボリック リンクをたどらず、マウント ポイントを横断せず、合計をst_blocks*2(つまり、1024 バイト単位で) 出力します。つまり、ファイルとディレクトリのコンテンツに割り当てられた 1024 バイト単位の数 --ディスク使用量

一方、論理ファイルとディレクトリのサイズの合計は、

find DIRECTORY/ -printf '%s\n' | awk '{s+=$1} END { printf "%.0f\n", s / 1024.0 }'

これはディスク使用量とは関係なく、ファイルとディレクトリに格納されている見かけの情報量のみに依存します。通常、この測定は通常のファイルのみに限定されます。

find DIRECTORY/ -type f -printf '%s\n' | awk '{s+=$1} END { printf "%.0f\n", s / 1024.0 }'

したがって、基本的には、すべてのファイルを 1 つの巨大なファイルに連結した場合に得られるファイルの大きさをユーザーに伝えます。意味があるかどうかは議論の余地がありますが、多くのユーザーは有益だと感じています。とにかく、それは間違いなくディスク使用量とは異なる測定値です.


ファイル統計 ( を参照man 2 fstat) ではst_blocks、ファイルの内容に割り当てられている 512 バイト単位の数と、ファイルst_sizeの論理サイズが示されます。

ほとんどのファイルシステムはスパース ファイルをサポートしています。これは、 を使用してファイルを拡大するtruncate()か、現在のファイル サイズよりも大きいファイル オフセットに書き込むことによって、ファイル システムがスキップされた部分をまったく保存しないことを意味します。ただし、その部分を読んでも問題ありません。常にすべてゼロとして読み取られます。したがって、大部分がゼロの場合、巨大なファイルは数ブロックしか消費しない可能性があります。(正確には、「スキップされたゼロ」。ファイルを作成するときに、ゼロを書き込むだけではスパース ファイルは生成されません。スパース ファイルを生成するには、アプリケーションでゼロの書き込みをスキップする必要があります。)

一部のファイルシステムの一部のファイルで間接ブロックが使用されるため、ブロックの数がファイルサイズに基づいて想定されるよりも大きくなる可能性もあります。ファイルが断片化されているか、特殊なファイルであるため、「余分なブロック」が割り当てられ、考慮される場合があります。とにかく、すべての典型的なファイルシステムでは、割り当てられたブロックの数は、ファイルシステムの割り当てサイズの倍数に切り上げられます。


あなたの場合、total sizeシンボリックリンクによって参照される重複を含め、すべてのファイルとディレクトリの内容を単一のファイルに連結する場合のファイルの論理的な長さです。

あなたの場合、シンボリックリンクが元のファイルのコピーに置き換えられた場合total real size、すべてのファイルとディレクトリの合計に割り当てられたディスク容量を説明します。

に変更すると

flags = FTW_MOUNT | FTW_PHYS;

total real sizeその一致を取得する必要がありますdu -s

于 2013-09-22T00:02:08.500 に答える