Edited at

C言語で、作成したファイルが断片化しないようにする方法。(Linux編)

More than 5 years have passed since last update.

creat()などで作成したファイルに、大きなデータを書き込むとファイルの断片化が起こるが、データを書き込む前に領域を確保しておけば、断片化が起こる可能性を減らすことが出来る。


sample.c

#define _GNU_SOURCE


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <linux/falloc.h>

int main(void)
{
int fd = creat("sample.dat", S_IRUSR | S_IWUSR);

/* 領域を128MB確保する */
fallocate(fd, FALLOC_FL_KEEP_SIZE, 0, 1024 * 1024 * 128);

/* ここにデータを書き込む処理を書く */

return 0;
}


上記のコードを実行して作成したsample.datに対して、filefragコマンドを実行すると以下のように表示される。

$filefrag -v sample.dat 

Filesystem type is: ef53
File size of sample.dat is 0 (0 blocks, blocksize 4096)
ext logical physical expected length flags
0 0 4435968 30720 unwritten,eof
1 30720 4466688 2048 unwritten,eof
sample.dat: 1 extent found

ファイルサイズは0のままだが、連続した実領域が確保されているのが確認できる。

上記の通り、fallocate()はファイルサイズ(の値)を変更しないので、そこが気になる場合は代わりにposix_fallocate()を使用する。


sample2.c

#define _GNU_SOURCE


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <linux/falloc.h>

int main(void)
{
int fd = creat("sample2.dat", S_IRUSR | S_IWUSR);

/* 領域を256MB確保する */
posix_fallocate(fd, 0, 1024 * 1024 * 256);

/* ここにデータを書き込む処理を書く */

return 0;
}


上記のコードを実行して作成したファイルに対して、filefragコマンドを実行すると以下のようになる。

$filefrag -v sample2.dat 

Filesystem type is: ef53
File size of sample2.dat is 268435456 (65536 blocks, blocksize 4096)
ext logical physical expected length flags
0 0 4548608 30720 unwritten
1 30720 4579328 30720 unwritten
2 61440 4610048 4096 unwritten,eof
sample2.dat: 1 extent found

File sizeが268435456になっている。

ちなみに、fallocate()は本来、ディスクスペースを確実に確保するための関数、つまり、

データをファイルに書き出そうとしたけど、空きが無くて失敗したよ\(^o^)/

という状況を事前に防ぐ為の関数であって、断片化を防ぐためのものでは無い。連続領域が確保されるのはオマケみたいなもん。

他にも、fallocate()実行にかかるコストはほとんど無いとか、確保した領域は0で埋められている事が期待できるので、作成したファイルに対してゼロフィルする必要が無いとか、そういう利点もあったりする。

欠点は、使えるファイルシステムが限られる点。ext4やXFS、btrfsは対応しているが、今でもよく使われていると思われるext3は未対応。

あと、ext4は連続領域を確保する性能が低いので、fallocate()で128MBを超える領域を確保すると断片化しやすい。XFSはその辺は優秀で、1GBを超えても余裕で連続領域を確保できる。

WindowsではSetFilePointer()とSetEndOfFile()を使えば連続領域を確保出来るらしいので、誰かサンプルソース下さい。